1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/mem/gc_stats.h"
17 #include "ecmascript/mem/gc_key_stats.h"
18 #include "ecmascript/mem/heap-inl.h"
19
20 constexpr int DESCRIPTION_LENGTH = 25;
21 constexpr int DATA_LENGTH = 8;
22
23 #define STATS_DESCRIPTION_FORMAT(description) \
24 std::left << std::setw(DESCRIPTION_LENGTH) << (description)
25
26 #define STATS_DATA_FORMAT(data) \
27 std::setw(DATA_LENGTH) << (data)
28
29 namespace panda::ecmascript {
PrintStatisticResult()30 void GCStats::PrintStatisticResult()
31 {
32 LOG_GC(INFO) << "/******************* GCStats statistic: *******************/";
33 PrintGCSummaryStatistic(GCType::PARTIAL_YOUNG_GC);
34 PrintGCSummaryStatistic(GCType::PARTIAL_OLD_GC);
35 PrintGCSummaryStatistic(GCType::COMPRESS_GC);
36 PrintGCMemoryStatistic();
37 }
38
PrintGCStatistic()39 void GCStats::PrintGCStatistic()
40 {
41 ASSERT(heap_ != nullptr);
42 ASSERT(heap_->GetEcmaVM() != nullptr);
43 if (heap_->GetEcmaVM()->GetJSOptions().EnableGCTracer() || CheckIfLongTimePause()) {
44 LOG_GC(INFO) << " [ " << GetGCTypeName() << " ] "
45 << sizeToMB(recordData_[(uint8_t)RecordData::START_OBJ_SIZE]) << " ("
46 << sizeToMB(recordData_[(uint8_t)RecordData::START_COMMIT_SIZE]) << ") -> "
47 << sizeToMB(recordData_[(uint8_t)RecordData::END_OBJ_SIZE]) << " ("
48 << sizeToMB(recordData_[(uint8_t)RecordData::END_COMMIT_SIZE]) << ") MB, "
49 << scopeDuration_[Scope::ScopeId::TotalGC] << "(+"
50 << GetConcurrrentMarkDuration()
51 << ")ms, " << GCReasonToString(reason_);
52 LOG_GC(INFO) << "IsInBackground: " << heap_->IsInBackground() << "; "
53 << "SensitiveStatus: " << static_cast<int>(heap_->GetSensitiveStatus()) << "; "
54 << "StartupStatus: " << std::to_string(static_cast<int>(heap_->GetStartupStatus())) << "; "
55 << "BundleName: " << heap_->GetEcmaVM()->GetBundleName()
56 << "; Young: " << std::to_string(heap_->GetNewSpace()->GetCommittedSize())
57 << "; Old: " << std::to_string(heap_->GetOldSpace()->GetCommittedSize())
58 << "; TotalCommit" << std::to_string(heap_->GetCommittedSize());
59 // print verbose gc statsistics
60 PrintVerboseGCStatistic();
61 }
62 GCFinishTrace();
63 InitializeRecordList();
64 }
65
GCReasonToString()66 const char *GCStats::GCReasonToString()
67 {
68 return GCReasonToString(reason_);
69 }
70
GCReasonToString(GCReason reason)71 const char *GCStats::GCReasonToString(GCReason reason)
72 {
73 switch (reason) {
74 case GCReason::ALLOCATION_LIMIT:
75 return "Memory reach limit";
76 case GCReason::ALLOCATION_FAILED:
77 return "Allocate object failed";
78 case GCReason::IDLE:
79 return "Idle time task";
80 case GCReason::SWITCH_BACKGROUND:
81 return "Switch to background";
82 case GCReason::EXTERNAL_TRIGGER:
83 return "Externally triggered";
84 case GCReason::WORKER_DESTRUCTION:
85 return "Worker Destruction";
86 case GCReason::TRIGGER_BY_JS:
87 return "Trigger by JS";
88 case GCReason::TRIGGER_BY_ARKUI:
89 return "Trigger by ArkUI";
90 case GCReason::TRIGGER_BY_ABILITY:
91 return "Trigger by AbilityRuntime";
92 case GCReason::TRIGGER_BY_MEM_TOOLS:
93 return "Trigger by Mem tools";
94 case GCReason::TRIGGER_BY_TASKPOOL:
95 return "Trigger by taskPool";
96 default: // LCOV_EXCL_BR_LINE
97 return "Other";
98 }
99 }
100
GetConcurrrentMarkDuration()101 float GCStats::GetConcurrrentMarkDuration()
102 {
103 return concurrentMark_ ? scopeDuration_[Scope::ScopeId::ConcurrentMark] : 0;
104 }
105
PrintVerboseGCStatistic()106 void GCStats::PrintVerboseGCStatistic()
107 {
108 PrintGCDurationStatistic();
109 PrintGCMemoryStatistic();
110 PrintGCSummaryStatistic();
111 }
112
GCFinishTrace()113 void GCStats::GCFinishTrace()
114 {
115 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PartialGC::Finish" + std::to_string(heap_->IsConcurrentFullMark())
116 + ";Reason" + std::to_string(static_cast<int>(reason_))
117 + ";Sensitive" + std::to_string(static_cast<int>(heap_->GetSensitiveStatus()))
118 + ";IsInBackground" + std::to_string(heap_->IsInBackground())
119 + ";Startup" + std::to_string(heap_->OnStartupEvent())
120 + ";ConMark" + std::to_string(static_cast<int>(heap_->GetJSThread()->GetMarkStatus()))
121 + ";Young" + std::to_string(heap_->GetNewSpace()->GetCommittedSize())
122 + ";Old" + std::to_string(heap_->GetOldSpace()->GetCommittedSize())
123 + ";TotalCommit" + std::to_string(heap_->GetCommittedSize())
124 + ";NativeBindingSize" + std::to_string(heap_->GetNativeBindingSize())
125 + ";NativeLimitSize" + std::to_string(heap_->GetGlobalSpaceNativeLimit()));
126 }
127
PrintGCMemoryStatistic()128 void GCStats::PrintGCMemoryStatistic()
129 {
130 NativeAreaAllocator *nativeAreaAllocator = heap_->GetNativeAreaAllocator();
131 HeapRegionAllocator *heapRegionAllocator = heap_->GetHeapRegionAllocator();
132 LOG_GC(INFO) << "/****************** GC Memory statistic: *****************/";
133 LOG_GC(INFO) << "AllSpaces used:"
134 << STATS_DATA_FORMAT(sizeToKB(heap_->GetHeapObjectSize())) << "KB"
135 << " committed:"
136 << STATS_DATA_FORMAT(sizeToKB(heap_->GetCommittedSize())) << "KB\n"
137 << "ActiveSemiSpace used:"
138 << STATS_DATA_FORMAT(sizeToKB(heap_->GetNewSpace()->GetHeapObjectSize())) << "KB"
139 << " committed:"
140 << STATS_DATA_FORMAT(sizeToKB(heap_->GetNewSpace()->GetCommittedSize())) << "KB\n"
141 << "OldSpace used:"
142 << STATS_DATA_FORMAT(sizeToKB(heap_->GetOldSpace()->GetHeapObjectSize())) << "KB"
143 << " committed:"
144 << STATS_DATA_FORMAT(sizeToKB(heap_->GetOldSpace()->GetCommittedSize())) << "KB\n"
145 << "HugeObjectSpace used:"
146 << STATS_DATA_FORMAT(sizeToKB(heap_->GetHugeObjectSpace()->GetHeapObjectSize())) << "KB"
147 << " committed:"
148 << STATS_DATA_FORMAT(sizeToKB(heap_->GetHugeObjectSpace()->GetCommittedSize())) << "KB\n"
149 << "NonMovableSpace used:"
150 << STATS_DATA_FORMAT(sizeToKB(heap_->GetNonMovableSpace()->GetHeapObjectSize())) << "KB"
151 << " committed:"
152 << STATS_DATA_FORMAT(sizeToKB(heap_->GetNonMovableSpace()->GetCommittedSize())) << "KB\n"
153 << "MachineCodeSpace used:"
154 << STATS_DATA_FORMAT(sizeToKB(heap_->GetMachineCodeSpace()->GetHeapObjectSize())) << "KB"
155 << " committed:"
156 << STATS_DATA_FORMAT(sizeToKB(heap_->GetMachineCodeSpace()->GetCommittedSize())) << "KB\n"
157 << "HugeMachineCodeSpace used:"
158 << STATS_DATA_FORMAT(sizeToKB(heap_->GetHugeMachineCodeSpace()->GetHeapObjectSize())) << "KB"
159 << " committed:"
160 << STATS_DATA_FORMAT(sizeToKB(heap_->GetHugeMachineCodeSpace()->GetCommittedSize())) << "KB\n"
161 << "SnapshotSpace used:"
162 << STATS_DATA_FORMAT(sizeToKB(heap_->GetSnapshotSpace()->GetHeapObjectSize())) << "KB"
163 << " committed:"
164 << STATS_DATA_FORMAT(sizeToKB(heap_->GetSnapshotSpace()->GetCommittedSize())) << "KB\n"
165 << "AppSpawnSpace used:"
166 << STATS_DATA_FORMAT(sizeToKB(heap_->GetAppSpawnSpace()->GetHeapObjectSize())) << "KB"
167 << " committed:"
168 << STATS_DATA_FORMAT(sizeToKB(heap_->GetAppSpawnSpace()->GetCommittedSize())) << "KB";
169
170 LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("Anno memory usage size:")
171 << STATS_DATA_FORMAT(sizeToMB(heapRegionAllocator->GetAnnoMemoryUsage())) << "MB\n"
172 << STATS_DESCRIPTION_FORMAT("Native memory usage size:")
173 << STATS_DATA_FORMAT(sizeToMB(nativeAreaAllocator->GetNativeMemoryUsage())) << "MB\n"
174 << STATS_DESCRIPTION_FORMAT("NativeBindingSize:")
175 << STATS_DATA_FORMAT(sizeToKB(heap_->GetNativeBindingSize())) << "KB\n"
176 << STATS_DESCRIPTION_FORMAT("NativeLimitSize:")
177 << STATS_DATA_FORMAT(sizeToKB(heap_->GetGlobalSpaceNativeLimit())) << "KB\n"
178 << STATS_DESCRIPTION_FORMAT("ArrayBufferNativeSize:")
179 << STATS_DATA_FORMAT(sizeToKB(heap_->GetNativeAreaAllocator()->GetArrayBufferNativeSize()))
180 << "KB\n"
181 << STATS_DESCRIPTION_FORMAT("RegExpByteCodeNativeSize:")
182 << STATS_DATA_FORMAT(sizeToKB(heap_->GetNativeAreaAllocator()->GetRegExpNativeSize())) << "KB\n"
183 << STATS_DESCRIPTION_FORMAT("ChunkNativeSize:")
184 << STATS_DATA_FORMAT(sizeToKB(heap_->GetNativeAreaAllocator()->GetChunkNativeSize())) << "KB";
185 switch (gcType_) {
186 case GCType::PARTIAL_YOUNG_GC: {
187 double copiedRate = double(GetRecordData(RecordData::YOUNG_ALIVE_SIZE)) /
188 GetRecordData(RecordData::YOUNG_COMMIT_SIZE);
189 double premotedRate = double(GetRecordData(RecordData::YOUNG_PROMOTE_SIZE)) /
190 GetRecordData(RecordData::YOUNG_COMMIT_SIZE);
191 double survivalRate = std::min(copiedRate + premotedRate, 1.0);
192 LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("Young copied rate:") << STATS_DATA_FORMAT(copiedRate) << "\n"
193 << STATS_DESCRIPTION_FORMAT("Young promoted rate:") << STATS_DATA_FORMAT(premotedRate) << "\n"
194 << STATS_DESCRIPTION_FORMAT("Young survival rate:") << STATS_DATA_FORMAT(survivalRate);
195 break;
196 }
197 case GCType::PARTIAL_OLD_GC: {
198 LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("Heap alive rate:")
199 << STATS_DATA_FORMAT(double(GetRecordData(RecordData::OLD_ALIVE_SIZE)) /
200 GetRecordData(RecordData::OLD_COMMIT_SIZE));
201 break;
202 }
203 case GCType::COMPRESS_GC: {
204 LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("Heap alive rate:")
205 << STATS_DATA_FORMAT(double(GetRecordData(RecordData::COMPRESS_ALIVE_SIZE)) /
206 GetRecordData(RecordData::COMPRESS_COMMIT_SIZE));
207 break;
208 }
209 default:
210 break;
211 }
212 }
213
PrintGCDurationStatistic()214 void GCStats::PrintGCDurationStatistic()
215 {
216 LOG_GC(INFO) << "/***************** GC Duration statistic: ****************/";
217 switch (gcType_) {
218 case GCType::PARTIAL_YOUNG_GC:
219 case GCType::PARTIAL_OLD_GC:
220 LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("TotalGC:")
221 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::TotalGC]) << "ms\n"
222 << STATS_DESCRIPTION_FORMAT("Initialize:")
223 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Initialize]) << "ms\n"
224 << STATS_DESCRIPTION_FORMAT("Mark:")
225 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Mark]) << "ms\n"
226 << STATS_DESCRIPTION_FORMAT("MarkRoots:")
227 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::MarkRoots]) << "ms\n"
228 << STATS_DESCRIPTION_FORMAT("ConcurrentMark pause:")
229 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::ConcurrentMark]) << "ms\n"
230 << STATS_DESCRIPTION_FORMAT("WaitConcurrentMarkFinish:")
231 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::WaitConcurrentMarkFinished]) << "ms\n"
232 << STATS_DESCRIPTION_FORMAT("ReMark:")
233 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::ReMark]) << "ms\n"
234 << STATS_DESCRIPTION_FORMAT("ProcessSharedGCRSetWorkList:")
235 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::ProcessSharedGCRSetWorkList]) << "ms\n"
236 << STATS_DESCRIPTION_FORMAT("Sweep:")
237 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Sweep]) << "ms\n"
238 << STATS_DESCRIPTION_FORMAT("ClearNativeObject:")
239 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::ClearNativeObject]) << "ms\n"
240 << STATS_DESCRIPTION_FORMAT("Evacuate:")
241 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Evacuate]) << "ms\n"
242 << STATS_DESCRIPTION_FORMAT("UpdateReference:")
243 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::UpdateReference]) << "ms\n"
244 << STATS_DESCRIPTION_FORMAT("UpdateWeekRef:")
245 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::UpdateWeekRef]) << "ms\n"
246 << STATS_DESCRIPTION_FORMAT("UpdateRoot:")
247 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::UpdateRoot]) << "ms\n"
248 << STATS_DESCRIPTION_FORMAT("ProceeWorkload:")
249 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::ProceeWorkload]) << "ms\n"
250 << STATS_DESCRIPTION_FORMAT("EvacuateSpace:")
251 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::EvacuateSpace]) << "ms\n"
252 << STATS_DESCRIPTION_FORMAT("EvacuateRegion:")
253 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::EvacuateRegion]) << "ms\n"
254 << STATS_DESCRIPTION_FORMAT("WaitFinish:")
255 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::WaitFinish]) << "ms\n"
256 << STATS_DESCRIPTION_FORMAT("Finish:")
257 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Finish]) << "ms";
258 break;
259 case GCType::COMPRESS_GC:
260 LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("TotalGC:")
261 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::TotalGC]) << "ms\n"
262 << STATS_DESCRIPTION_FORMAT("ProcessSharedGCRSetWorkList:")
263 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::ProcessSharedGCRSetWorkList]) << "ms\n"
264 << STATS_DESCRIPTION_FORMAT("Initialize:")
265 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Initialize]) << "ms\n"
266 << STATS_DESCRIPTION_FORMAT("Mark:")
267 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Mark]) << "ms\n"
268 << STATS_DESCRIPTION_FORMAT("MarkRoots:")
269 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::MarkRoots]) << "ms\n"
270 << STATS_DESCRIPTION_FORMAT("Sweep:")
271 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Sweep]) << "ms\n"
272 << STATS_DESCRIPTION_FORMAT("Finish:")
273 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Finish]) << "ms";
274 break;
275 default: // LCOV_EXCL_BR_LINE
276 break;
277 }
278 }
279
CheckIfNeedPrint(GCType type)280 bool GCStats::CheckIfNeedPrint(GCType type)
281 {
282 uint32_t gcCount = 0;
283 switch (type) {
284 case GCType::PARTIAL_YOUNG_GC:
285 gcCount = GetRecordData(RecordData::YOUNG_COUNT);
286 break;
287 case GCType::PARTIAL_OLD_GC:
288 gcCount = GetRecordData(RecordData::OLD_COUNT);
289 break;
290 case GCType::COMPRESS_GC:
291 gcCount = GetRecordData(RecordData::COMPRESS_COUNT);
292 break;
293 default: // LCOV_EXCL_BR_LINE
294 break;
295 }
296
297 if (gcCount > 0) {
298 return true;
299 }
300 return false;
301 }
302
PrintGCSummaryStatistic(GCType type)303 void GCStats::PrintGCSummaryStatistic(GCType type)
304 {
305 if (type != GCType::START && !CheckIfNeedPrint(type)) {
306 return;
307 } else {
308 type = type == GCType::START ? gcType_ : type;
309 }
310 LOG_GC(INFO) << "/***************** GC summary statistic: *****************/";
311 switch (type) {
312 case GCType::PARTIAL_YOUNG_GC: {
313 double copiedRate = double(GetRecordData(RecordData::YOUNG_TOTAL_ALIVE)) /
314 GetRecordData(RecordData::YOUNG_TOTAL_COMMIT);
315 double promotedRate = double(GetRecordData(RecordData::YOUNG_TOTAL_PROMOTE)) /
316 GetRecordData(RecordData::YOUNG_TOTAL_COMMIT);
317 double survivalRate = std::min(copiedRate + promotedRate, 1.0);
318 LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("YoungGC occurs count")
319 << STATS_DATA_FORMAT(GetRecordData(RecordData::YOUNG_COUNT)) << "\n"
320 << STATS_DESCRIPTION_FORMAT("YoungGC max pause:")
321 << STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::YOUNG_MAX_PAUSE)) << "ms\n"
322 << STATS_DESCRIPTION_FORMAT("YoungGC min pause:")
323 << STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::YOUNG_MIN_PAUSE)) << "ms\n"
324 << STATS_DESCRIPTION_FORMAT("YoungGC average pause:")
325 << STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::YOUNG_TOTAL_PAUSE) /
326 GetRecordData(RecordData::YOUNG_COUNT)) << "ms\n"
327 << STATS_DESCRIPTION_FORMAT("Young average copied rate:") << STATS_DATA_FORMAT(copiedRate) << "\n"
328 << STATS_DESCRIPTION_FORMAT("Young average promoted rate:") << STATS_DATA_FORMAT(promotedRate) << "\n"
329 << STATS_DESCRIPTION_FORMAT("Young average survival rate:") << STATS_DATA_FORMAT(survivalRate);
330 break;
331 }
332 case GCType::PARTIAL_OLD_GC: {
333 LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("OldGC occurs count")
334 << STATS_DATA_FORMAT(GetRecordData(RecordData::OLD_COUNT)) << "\n"
335 << STATS_DESCRIPTION_FORMAT("OldGC max pause:")
336 << STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::OLD_MAX_PAUSE)) << "ms\n"
337 << STATS_DESCRIPTION_FORMAT("OldGC min pause:")
338 << STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::OLD_MIN_PAUSE)) << "ms\n"
339 << STATS_DESCRIPTION_FORMAT("OldGC average pause:")
340 << STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::OLD_TOTAL_PAUSE) /
341 GetRecordData(RecordData::OLD_COUNT)) << "ms\n"
342 << STATS_DESCRIPTION_FORMAT("Heap average alive rate:")
343 << STATS_DATA_FORMAT(double(GetRecordData(RecordData::OLD_TOTAL_ALIVE)) /
344 GetRecordData(RecordData::OLD_TOTAL_COMMIT));
345 break;
346 }
347 case GCType::COMPRESS_GC: {
348 LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("CompressGC occurs count")
349 << STATS_DATA_FORMAT(GetRecordData(RecordData::COMPRESS_COUNT)) << "\n"
350 << STATS_DESCRIPTION_FORMAT("CompressGC max pause:")
351 << STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::COMPRESS_MAX_PAUSE)) << "ms\n"
352 << STATS_DESCRIPTION_FORMAT("CompressGC min pause:")
353 << STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::COMPRESS_MIN_PAUSE)) << "ms\n"
354 << STATS_DESCRIPTION_FORMAT("CompressGC average pause:")
355 << STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::COMPRESS_TOTAL_PAUSE) /
356 GetRecordData(RecordData::COMPRESS_COUNT)) << "ms\n"
357 << STATS_DESCRIPTION_FORMAT("Heap average alive rate:")
358 << STATS_DATA_FORMAT(double(GetRecordData(RecordData::COMPRESS_TOTAL_ALIVE)) /
359 GetRecordData(RecordData::COMPRESS_TOTAL_COMMIT));
360 break;
361 }
362 default: // LCOV_EXCL_BR_LINE
363 break;
364 }
365 }
366
GetAccumulatedAllocateSize()367 size_t GCStats::GetAccumulatedAllocateSize()
368 {
369 return accumulatedFreeSize_ + heap_->GetHeapObjectSize();
370 }
371
RecordStatisticBeforeGC(TriggerGCType gcType,GCReason reason)372 void GCStats::RecordStatisticBeforeGC(TriggerGCType gcType, GCReason reason)
373 {
374 SetRecordData(RecordData::START_OBJ_SIZE, heap_->GetHeapObjectSize());
375 SetRecordData(RecordData::START_COMMIT_SIZE, heap_->GetCommittedSize());
376 SetRecordData(RecordData::START_YOUNG_OBJ_SIZE, heap_->GetNewSpace()->GetHeapObjectSize());
377 SetRecordData(RecordData::START_NATIVE_POINTER_NUM, heap_->GetNativePointerListSize());
378 gcType_ = GetGCType(gcType);
379 reason_ = reason;
380
381 switch (gcType_) {
382 case GCType::PARTIAL_YOUNG_GC: {
383 size_t youngCommitSize = heap_->GetNewSpace()->GetCommittedSize();
384 SetRecordData(RecordData::YOUNG_COMMIT_SIZE, youngCommitSize);
385 IncreaseRecordData(RecordData::YOUNG_TOTAL_COMMIT, youngCommitSize);
386 break;
387 }
388 case GCType::PARTIAL_OLD_GC: {
389 size_t oldCommitSize = heap_->GetCommittedSize();
390 SetRecordData(RecordData::OLD_COMMIT_SIZE, oldCommitSize);
391 IncreaseRecordData(RecordData::OLD_TOTAL_COMMIT, oldCommitSize);
392 break;
393 }
394 case GCType::COMPRESS_GC: {
395 size_t compressCommitSize = heap_->GetCommittedSize();
396 SetRecordData(RecordData::COMPRESS_COMMIT_SIZE, compressCommitSize);
397 IncreaseRecordData(RecordData::COMPRESS_TOTAL_COMMIT, compressCommitSize);
398 break;
399 }
400 default: // LCOV_EXCL_BR_LINE
401 break;
402 }
403 ProcessBeforeLongGCStats();
404 }
405
RecordStatisticAfterGC()406 void GCStats::RecordStatisticAfterGC()
407 {
408 ASSERT(heap_ != nullptr);
409 SetRecordData(RecordData::END_OBJ_SIZE, heap_->GetHeapObjectSize());
410 SetRecordData(RecordData::END_COMMIT_SIZE, heap_->GetCommittedSize());
411
412 float duration = scopeDuration_[Scope::ScopeId::TotalGC];
413 switch (gcType_) {
414 case GCType::PARTIAL_YOUNG_GC: {
415 if (GetRecordData(RecordData::YOUNG_COUNT) == 0) {
416 SetRecordDuration(RecordDuration::YOUNG_MIN_PAUSE, duration);
417 SetRecordDuration(RecordDuration::YOUNG_MAX_PAUSE, duration);
418 } else {
419 SetRecordDuration(RecordDuration::YOUNG_MIN_PAUSE,
420 std::min(GetRecordDuration(RecordDuration::YOUNG_MIN_PAUSE), duration));
421 SetRecordDuration(RecordDuration::YOUNG_MAX_PAUSE,
422 std::max(GetRecordDuration(RecordDuration::YOUNG_MAX_PAUSE), duration));
423 }
424 IncreaseRecordData(RecordData::YOUNG_COUNT);
425 IncreaseRecordDuration(RecordDuration::YOUNG_TOTAL_PAUSE, duration);
426 size_t youngAliveSize = heap_->GetNewSpace()->GetHeapObjectSize();
427 SetRecordData(RecordData::YOUNG_ALIVE_SIZE, youngAliveSize);
428 IncreaseRecordData(RecordData::YOUNG_TOTAL_ALIVE, youngAliveSize);
429 size_t promotedSize = heap_->GetPromotedSize();
430 SetRecordData(RecordData::YOUNG_PROMOTE_SIZE, promotedSize);
431 IncreaseRecordData(RecordData::YOUNG_TOTAL_PROMOTE, promotedSize);
432 break;
433 }
434 case GCType::PARTIAL_OLD_GC: {
435 if (GetRecordData(RecordData::OLD_COUNT) == 0) {
436 SetRecordDuration(RecordDuration::OLD_MIN_PAUSE, duration);
437 SetRecordDuration(RecordDuration::OLD_MAX_PAUSE, duration);
438 } else {
439 SetRecordDuration(RecordDuration::OLD_MIN_PAUSE,
440 std::min(GetRecordDuration(RecordDuration::OLD_MIN_PAUSE), duration));
441 SetRecordDuration(RecordDuration::OLD_MAX_PAUSE,
442 std::max(GetRecordDuration(RecordDuration::OLD_MAX_PAUSE), duration));
443 }
444 IncreaseRecordData(RecordData::OLD_COUNT);
445 IncreaseRecordDuration(RecordDuration::OLD_TOTAL_PAUSE, duration);
446 size_t oldAliveSize = heap_->GetHeapObjectSize();
447 SetRecordData(RecordData::OLD_ALIVE_SIZE, oldAliveSize);
448 IncreaseRecordData(RecordData::OLD_TOTAL_ALIVE, oldAliveSize);
449 break;
450 }
451 case GCType::COMPRESS_GC: {
452 if (GetRecordData(RecordData::COMPRESS_COUNT) == 0) {
453 SetRecordDuration(RecordDuration::COMPRESS_MIN_PAUSE, duration);
454 SetRecordDuration(RecordDuration::COMPRESS_MAX_PAUSE, duration);
455 } else {
456 SetRecordDuration(RecordDuration::COMPRESS_MIN_PAUSE,
457 std::min(GetRecordDuration(RecordDuration::COMPRESS_MIN_PAUSE), duration));
458 SetRecordDuration(RecordDuration::COMPRESS_MAX_PAUSE,
459 std::max(GetRecordDuration(RecordDuration::COMPRESS_MAX_PAUSE), duration));
460 }
461 IncreaseRecordData(RecordData::COMPRESS_COUNT);
462 IncreaseRecordDuration(RecordDuration::COMPRESS_TOTAL_PAUSE, duration);
463 size_t compressAliveSize = heap_->GetHeapObjectSize();
464 SetRecordData(RecordData::COMPRESS_ALIVE_SIZE, compressAliveSize);
465 IncreaseRecordData(RecordData::COMPRESS_TOTAL_ALIVE, compressAliveSize);
466 break;
467 }
468 default:
469 break;
470 }
471 RecordGCSpeed();
472
473 if (gcType_ == GCType::COMPRESS_GC && scopeDuration_[Scope::ScopeId::TotalGC] > longPauseTime_) {
474 IncreaseFullGCLongTimeCount();
475 }
476 IncreaseTotalDuration(scopeDuration_[Scope::ScopeId::TotalGC]);
477 IncreaseAccumulatedFreeSize(GetRecordData(RecordData::START_OBJ_SIZE) -
478 GetRecordData(RecordData::END_OBJ_SIZE));
479 ProcessAfterLongGCStats();
480 }
481
ProcessAfterLongGCStats()482 void GCStats::ProcessAfterLongGCStats()
483 {
484 LongGCStats *longGCStats = GetLongGCStats();
485 float gcTotalTime = GetScopeDuration(GCStats::Scope::ScopeId::TotalGC);
486 if (IsLongGC(reason_, heap_->InSensitiveStatus(), heap_->IsInBackground(), gcTotalTime)) {
487 longGCStats->SetGCType(static_cast<int>(gcType_));
488 longGCStats->SetGCReason(static_cast<int>(reason_));
489 longGCStats->SetGCIsSensitive(heap_->InSensitiveStatus());
490 longGCStats->SetGCIsInBackground(heap_->IsInBackground());
491 longGCStats->SetGCTotalTime(gcTotalTime);
492 longGCStats->SetGCMarkTime(GetScopeDuration(GCStats::Scope::ScopeId::Mark));
493 longGCStats->SetGCEvacuateTime(GetScopeDuration(GCStats::Scope::ScopeId::Evacuate));
494 longGCStats->SetGCUpdateRootTime(GetScopeDuration(GCStats::Scope::ScopeId::UpdateRoot));
495 longGCStats->SetGCUpdateWeekRefTime(GetScopeDuration(GCStats::Scope::ScopeId::UpdateWeekRef));
496 longGCStats->SetGCUpdateReferenceTime(GetScopeDuration(GCStats::Scope::ScopeId::UpdateReference));
497 longGCStats->SetGCSweepNewToOldTime(GetScopeDuration(GCStats::Scope::ScopeId::SweepNewToOldRegions));
498 longGCStats->SetGCFinalizeTime(GetScopeDuration(GCStats::Scope::ScopeId::Finalize));
499 longGCStats->SetGCInvokeCallbackTime(GetScopeDuration(GCStats::Scope::ScopeId::InvokeNativeFinalizeCallbacks));
500 longGCStats->SetAfterGCTotalMemUsed(heap_->GetHeapObjectSize());
501 longGCStats->SetAfterGCTotalMemCommitted(heap_->GetCommittedSize());
502 longGCStats->SetAfterGCActiveMemUsed(heap_->GetNewSpace()->GetHeapObjectSize());
503 longGCStats->SetAfterGCActiveMemCommitted(heap_->GetNewSpace()->GetCommittedSize());
504 longGCStats->SetAfterGCOldMemUsed(heap_->GetOldSpace()->GetHeapObjectSize());
505 longGCStats->SetAfterGCOldMemCommitted(heap_->GetOldSpace()->GetCommittedSize());
506 longGCStats->SetAfterGCHugeMemUsed(heap_->GetHugeObjectSpace()->GetHeapObjectSize());
507 longGCStats->SetAfterGCHugeMemCommitted(heap_->GetHugeObjectSpace()->GetCommittedSize());
508 longGCStats->SetAfterGCNativeBindingSize(heap_->GetNativeBindingSize());
509 longGCStats->SetAfterGCNativeLimit(heap_->GetGlobalSpaceNativeLimit());
510 }
511 }
512
ProcessBeforeLongGCStats()513 void GCStats::ProcessBeforeLongGCStats()
514 {
515 LongGCStats *longGCStats = GetLongGCStats();
516 longGCStats->SetBeforeGCTotalMemUsed(heap_->GetHeapObjectSize());
517 longGCStats->SetBeforeGCTotalMemCommitted(heap_->GetCommittedSize());
518 longGCStats->SetBeforeGCActiveMemUsed(heap_->GetNewSpace()->GetHeapObjectSize());
519 longGCStats->SetBeforeGCActiveMemCommitted(heap_->GetNewSpace()->GetCommittedSize());
520 longGCStats->SetBeforeGCOldMemUsed(heap_->GetOldSpace()->GetHeapObjectSize());
521 longGCStats->SetBeforeGCOldMemCommitted(heap_->GetOldSpace()->GetCommittedSize());
522 longGCStats->SetBeforeGCHugeMemUsed(heap_->GetHugeObjectSpace()->GetHeapObjectSize());
523 longGCStats->SetBeforeGCHugeMemCommitted(heap_->GetHugeObjectSpace()->GetCommittedSize());
524 longGCStats->SetBeforeGCNativeBindingSize(heap_->GetNativeBindingSize());
525 longGCStats->SetBeforeGCNativeLimit(heap_->GetGlobalSpaceNativeLimit());
526 }
527
528 /*
529 | The Judgment criteria of Long GC
530 | IsInBackground | IsSensitive or Idle | GCTime |
531 | -----------------| ---------------------|---------|
532 | false | Sensitive | 33 |
533 | false | !Sensitive & !Idle | 33 |
534 | true | Idle | 200 |
535 | true | !Idle | 200 |
536 | true | Idle | 500 |
537 */
IsLongGC(GCReason gcReason,bool gcIsSensitive,bool gcIsInBackground,float gcTotalTime)538 bool GCStats::IsLongGC(GCReason gcReason, bool gcIsSensitive, bool gcIsInBackground, float gcTotalTime)
539 {
540 if (gcIsSensitive) {
541 if (gcTotalTime > GCKeyStats::GC_SENSITIVE_LONG_TIME) {
542 return true;
543 }
544 } else {
545 if (GCKeyStats::IsIdle(gcReason)) {
546 if (!gcIsInBackground && gcTotalTime > GCKeyStats::GC_IDLE_LONG_TIME) {
547 return true;
548 } else if (gcIsInBackground && gcTotalTime > GCKeyStats::GC_BACKGROUD_IDLE_LONG_TIME) {
549 return true;
550 }
551 } else {
552 if (!gcIsInBackground && gcTotalTime > GCKeyStats::GC_NOT_SENSITIVE_LONG_TIME) {
553 return true;
554 } else if (gcIsInBackground && gcTotalTime > GCKeyStats::GC_BACKGROUD_LONG_TIME) {
555 return true;
556 }
557 }
558 }
559 return false;
560 }
561
RecordGCSpeed()562 void GCStats::RecordGCSpeed()
563 {
564 double survivalRate = GetAvgSurvivalRate();
565 size_t clearNativeSpeed = GetRecordData(RecordData::START_NATIVE_POINTER_NUM) /
566 scopeDuration_[Scope::ScopeId::ClearNativeObject];
567
568 if (gcType_ == GCType::PARTIAL_YOUNG_GC) {
569 size_t objSize = GetRecordData(RecordData::START_YOUNG_OBJ_SIZE);
570 gcSpeed_[(uint8_t)SpeedData::MARK_SPEED] = objSize / scopeDuration_[Scope::ScopeId::Mark];
571 size_t evacuateSpeed = survivalRate * objSize / scopeDuration_[Scope::ScopeId::EvacuateSpace];
572 gcSpeed_[(uint8_t)SpeedData::YOUNG_EVACUATE_SPACE_SPEED] =
573 (evacuateSpeed + gcSpeed_[(uint8_t)SpeedData::YOUNG_EVACUATE_SPACE_SPEED]) / 2; // 2 means half
574 gcSpeed_[(uint8_t)SpeedData::YOUNG_CLEAR_NATIVE_OBJ_SPEED] =
575 (clearNativeSpeed + gcSpeed_[(uint8_t)SpeedData::YOUNG_CLEAR_NATIVE_OBJ_SPEED]) / 2; // 2 means half
576 size_t updateReferenceSpeed = GetRecordData(RecordData::START_OBJ_SIZE) /
577 scopeDuration_[Scope::ScopeId::UpdateReference];
578 gcSpeed_[(uint8_t)SpeedData::YOUNG_UPDATE_REFERENCE_SPEED] =
579 (updateReferenceSpeed + gcSpeed_[(uint8_t)SpeedData::YOUNG_UPDATE_REFERENCE_SPEED]) / 2; // 2 means half
580 } else if (gcType_ == GCType::PARTIAL_OLD_GC) {
581 gcSpeed_[(uint8_t)SpeedData::MARK_SPEED] =
582 GetRecordData(RecordData::START_OBJ_SIZE) / scopeDuration_[Scope::ScopeId::Mark];
583 size_t sweepSpeed = GetRecordData(RecordData::START_OBJ_SIZE) / scopeDuration_[Scope::ScopeId::Sweep];
584 gcSpeed_[(uint8_t)SpeedData::SWEEP_SPEED] =
585 (sweepSpeed + gcSpeed_[(uint8_t)SpeedData::SWEEP_SPEED]) / 2; // 2 means half
586 gcSpeed_[(uint8_t)SpeedData::OLD_CLEAR_NATIVE_OBJ_SPEED] =
587 (clearNativeSpeed + gcSpeed_[(uint8_t)SpeedData::OLD_CLEAR_NATIVE_OBJ_SPEED]) / 2; // 2 means half
588
589 size_t evacuateSpaceSpeed = (survivalRate * GetRecordData(RecordData::START_YOUNG_OBJ_SIZE) +
590 GetRecordData(RecordData::COLLECT_REGION_SET_SIZE)) / scopeDuration_[Scope::ScopeId::EvacuateSpace];
591 gcSpeed_[(uint8_t)SpeedData::OLD_EVACUATE_SPACE_SPEED] =
592 (evacuateSpaceSpeed + gcSpeed_[(uint8_t)SpeedData::OLD_EVACUATE_SPACE_SPEED]) / 2; // 2 means half
593
594 size_t updateReferenceSpeed = GetRecordData(RecordData::START_OBJ_SIZE) /
595 scopeDuration_[Scope::ScopeId::UpdateReference];
596 gcSpeed_[(uint8_t)SpeedData::UPDATE_REFERENCE_SPEED] =
597 (updateReferenceSpeed + gcSpeed_[(uint8_t)SpeedData::UPDATE_REFERENCE_SPEED]) / 2; // 2 means half
598 }
599 }
600
GetGCType(TriggerGCType gcType)601 GCType GCStats::GetGCType(TriggerGCType gcType)
602 {
603 if (heap_ && !heap_->IsReadyToConcurrentMark()) {
604 switch (heap_->GetMarkType()) {
605 case MarkType::MARK_YOUNG:
606 return GCType::PARTIAL_YOUNG_GC;
607 case MarkType::MARK_FULL:
608 return GCType::PARTIAL_OLD_GC;
609 default: // LCOV_EXCL_BR_LINE
610 return GCType::OTHER;
611 }
612 }
613 switch (gcType) {
614 case TriggerGCType::YOUNG_GC:
615 return GCType::PARTIAL_YOUNG_GC;
616 case TriggerGCType::OLD_GC:
617 return GCType::PARTIAL_OLD_GC;
618 case TriggerGCType::FULL_GC:
619 return GCType::COMPRESS_GC;
620 case TriggerGCType::SHARED_GC:
621 return GCType::SHARED_GC;
622 case TriggerGCType::SHARED_PARTIAL_GC:
623 return GCType::SHARED_PARTIAL_GC;
624 case TriggerGCType::SHARED_FULL_GC:
625 return GCType::SHARED_FULL_GC;
626 default:
627 return GCType::OTHER;
628 }
629 }
630
InitializeRecordList()631 void GCStats::InitializeRecordList()
632 {
633 for (float &duration : scopeDuration_) {
634 duration = 0.0f;
635 }
636 concurrentMark_ = false;
637 }
638
CheckIfLongTimePause()639 bool GCStats::CheckIfLongTimePause()
640 {
641 if (scopeDuration_[Scope::ScopeId::TotalGC] > longPauseTime_) {
642 LOG_GC(INFO) << "Has checked a long time gc";
643 return true;
644 }
645 return false;
646 }
647
PrintStatisticResult()648 void SharedGCStats::PrintStatisticResult()
649 {
650 LOG_GC(INFO) << "/******************* SharedGCStats statistic: *******************/";
651 PrintSharedGCSummaryStatistic();
652 PrintGCMemoryStatistic();
653 }
654
PrintGCStatistic()655 void SharedGCStats::PrintGCStatistic()
656 {
657 if (enableGCTracer_) {
658 LOG_GC(INFO) << " [ " << GetGCTypeName() << " ] "
659 << sizeToMB(recordData_[(uint8_t)RecordData::START_OBJ_SIZE]) << " ("
660 << sizeToMB(recordData_[(uint8_t)RecordData::START_COMMIT_SIZE]) << ") -> "
661 << sizeToMB(recordData_[(uint8_t)RecordData::END_OBJ_SIZE]) << " ("
662 << sizeToMB(recordData_[(uint8_t)RecordData::END_COMMIT_SIZE]) << ") MB, "
663 << scopeDuration_[Scope::ScopeId::TotalGC] << "ms, " << GCReasonToString(reason_);
664 PrintSharedGCDuration();
665 PrintGCMemoryStatistic();
666 PrintSharedGCSummaryStatistic();
667 }
668 SharedGCFinishTrace();
669 InitializeRecordList();
670 }
671
SharedGCFinishTrace()672 void SharedGCStats::SharedGCFinishTrace()
673 {
674 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Finish;Reason"
675 + std::to_string(static_cast<int>(reason_))
676 + ";Sensitive" + std::to_string(static_cast<int>(sHeap_->GetSensitiveStatus()))
677 + ";IsInBackground" + std::to_string(sHeap_->IsInBackground())
678 + ";Startup" + std::to_string(sHeap_->OnStartupEvent())
679 + ";Old" + std::to_string(sHeap_->GetOldSpace()->GetCommittedSize())
680 + ";huge" + std::to_string(sHeap_->GetHugeObjectSpace()->GetCommittedSize())
681 + ";NonMov" + std::to_string(sHeap_->GetNonMovableSpace()->GetCommittedSize())
682 + ";TotCommit" + std::to_string(sHeap_->GetCommittedSize())
683 + ";NativeBindingSize" + std::to_string(sHeap_->GetNativeSizeAfterLastGC())
684 + ";NativeLimitGC" + std::to_string(sHeap_->GetNativeSizeTriggerSharedGC())
685 + ";NativeLimitCM" + std::to_string(sHeap_->GetNativeSizeTriggerSharedCM()));
686 }
687
PrintSharedGCSummaryStatistic()688 void SharedGCStats::PrintSharedGCSummaryStatistic()
689 {
690 LOG_GC(INFO) << "/***************** GC summary statistic: *****************/";
691 LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("SharedGC occurs count")
692 << STATS_DATA_FORMAT(GetRecordData(RecordData::SHARED_COUNT)) << "\n"
693 << STATS_DESCRIPTION_FORMAT("SharedGC max pause:")
694 << STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::SHARED_MAX_PAUSE)) << "ms\n"
695 << STATS_DESCRIPTION_FORMAT("SharedGC min pause:")
696 << STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::SHARED_MIN_PAUSE)) << "ms\n"
697 << STATS_DESCRIPTION_FORMAT("SharedGC average pause:")
698 << STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::SHARED_TOTAL_PAUSE) /
699 GetRecordData(RecordData::SHARED_COUNT)) << "ms\n"
700 << STATS_DESCRIPTION_FORMAT("SharedHeap average alive rate:")
701 << STATS_DATA_FORMAT(double(GetRecordData(RecordData::SHARED_TOTAL_ALIVE)) /
702 GetRecordData(RecordData::SHARED_TOTAL_COMMIT));
703 }
704
PrintGCMemoryStatistic()705 void SharedGCStats::PrintGCMemoryStatistic()
706 {
707 NativeAreaAllocator *nativeAreaAllocator = sHeap_->GetNativeAreaAllocator();
708 HeapRegionAllocator *heapRegionAllocator = sHeap_->GetHeapRegionAllocator();
709 LOG_GC(INFO) << "/****************** GC Memory statistic: *****************/";
710 LOG_GC(INFO) << "AllSpaces used:"
711 << STATS_DATA_FORMAT(sizeToKB(sHeap_->GetHeapObjectSize())) << "KB"
712 << " committed:"
713 << STATS_DATA_FORMAT(sizeToKB(sHeap_->GetCommittedSize())) << "KB\n"
714 << "SharedOldSpace used:"
715 << STATS_DATA_FORMAT(sizeToKB(sHeap_->GetOldSpace()->GetHeapObjectSize())) << "KB"
716 << " committed:"
717 << STATS_DATA_FORMAT(sizeToKB(sHeap_->GetOldSpace()->GetCommittedSize())) << "KB\n"
718 << "SharedNonMovableSpace used:"
719 << STATS_DATA_FORMAT(sizeToKB(sHeap_->GetNonMovableSpace()->GetHeapObjectSize())) << "KB"
720 << " committed:"
721 << STATS_DATA_FORMAT(sizeToKB(sHeap_->GetNonMovableSpace()->GetCommittedSize())) << "KB\n"
722 << "SharedHugeObjectSpace used:"
723 << STATS_DATA_FORMAT(sizeToKB(sHeap_->GetHugeObjectSpace()->GetHeapObjectSize())) << "KB"
724 << " committed:"
725 << STATS_DATA_FORMAT(sizeToKB(sHeap_->GetHugeObjectSpace()->GetCommittedSize())) << "KB\n"
726 << "SharedAppSpawnSpace used:"
727 << STATS_DATA_FORMAT(sizeToKB(sHeap_->GetAppSpawnSpace()->GetHeapObjectSize())) << "KB"
728 << " committed:"
729 << STATS_DATA_FORMAT(sizeToKB(sHeap_->GetAppSpawnSpace()->GetCommittedSize())) << "KB";
730
731 LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("Anno memory usage size:")
732 << STATS_DATA_FORMAT(sizeToMB(heapRegionAllocator->GetAnnoMemoryUsage())) << "MB\n"
733 << STATS_DESCRIPTION_FORMAT("Native memory usage size:")
734 << STATS_DATA_FORMAT(sizeToMB(nativeAreaAllocator->GetNativeMemoryUsage())) << "MB\n"
735 << STATS_DESCRIPTION_FORMAT("NativeBindingSize:")
736 << STATS_DATA_FORMAT(sizeToKB(sHeap_->GetNativeSizeAfterLastGC())) << "KB\n"
737 << STATS_DESCRIPTION_FORMAT("NativeLimitGC:")
738 << STATS_DATA_FORMAT(sizeToKB(sHeap_->GetNativeSizeTriggerSharedGC())) << "KB\n"
739 << STATS_DESCRIPTION_FORMAT("NativeLimitCM:")
740 << STATS_DATA_FORMAT(sizeToKB(sHeap_->GetNativeSizeTriggerSharedCM())) << "KB\n";
741
742 LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("Heap alive rate:")
743 << STATS_DATA_FORMAT(double(GetRecordData(RecordData::SHARED_ALIVE_SIZE)) /
744 GetRecordData(RecordData::SHARED_COMMIT_SIZE));
745 }
746
PrintSharedGCDuration()747 void SharedGCStats::PrintSharedGCDuration()
748 {
749 LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("TotalGC:")
750 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::TotalGC]) << "ms\n"
751 << STATS_DESCRIPTION_FORMAT("Initialize:")
752 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Initialize]) << "ms\n"
753 << STATS_DESCRIPTION_FORMAT("Mark:")
754 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Mark]) << "ms\n"
755 << STATS_DESCRIPTION_FORMAT("Evacuate:")
756 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Evacuate]) << "ms\n"
757 << STATS_DESCRIPTION_FORMAT("UpdateReference:")
758 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::UpdateReference]) << "ms\n"
759 << STATS_DESCRIPTION_FORMAT("Sweep:")
760 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Sweep]) << "ms\n"
761 << STATS_DESCRIPTION_FORMAT("Finish:")
762 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Finish]) << "ms\n"
763 << STATS_DESCRIPTION_FORMAT("SuspendAll:")
764 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::SuspendAll]) << "ms\n"
765 << STATS_DESCRIPTION_FORMAT("ResumeAll:")
766 << STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::ResumeAll]) << "ms";
767 }
768
GetAccumulatedAllocateSize()769 size_t SharedGCStats::GetAccumulatedAllocateSize()
770 {
771 return accumulatedFreeSize_ + sHeap_->GetHeapObjectSize();
772 }
773
RecordStatisticBeforeGC(TriggerGCType gcType,GCReason reason)774 void SharedGCStats::RecordStatisticBeforeGC(TriggerGCType gcType, GCReason reason)
775 {
776 size_t commitSize = sHeap_->GetCommittedSize();
777 SetRecordData(RecordData::START_OBJ_SIZE, sHeap_->GetHeapObjectSize());
778 SetRecordData(RecordData::START_COMMIT_SIZE, commitSize);
779 SetRecordData(RecordData::SHARED_COMMIT_SIZE, commitSize);
780 IncreaseRecordData(RecordData::SHARED_TOTAL_COMMIT, commitSize);
781 gcType_ = GetGCType(gcType);
782 reason_ = reason;
783 ProcessBeforeLongGCStats();
784 }
785
RecordStatisticAfterGC()786 void SharedGCStats::RecordStatisticAfterGC()
787 {
788 SetRecordData(RecordData::END_OBJ_SIZE, sHeap_->GetHeapObjectSize());
789 SetRecordData(RecordData::END_COMMIT_SIZE, sHeap_->GetCommittedSize());
790
791 float duration = scopeDuration_[Scope::ScopeId::TotalGC];
792 if (GetRecordData(RecordData::SHARED_COUNT) == 0) {
793 SetRecordDuration(RecordDuration::SHARED_MIN_PAUSE, duration);
794 SetRecordDuration(RecordDuration::SHARED_MAX_PAUSE, duration);
795 } else {
796 SetRecordDuration(RecordDuration::SHARED_MIN_PAUSE,
797 std::min(GetRecordDuration(RecordDuration::SHARED_MIN_PAUSE), duration));
798 SetRecordDuration(RecordDuration::SHARED_MAX_PAUSE,
799 std::max(GetRecordDuration(RecordDuration::SHARED_MAX_PAUSE), duration));
800 }
801 IncreaseRecordData(RecordData::SHARED_COUNT);
802 IncreaseRecordDuration(RecordDuration::SHARED_TOTAL_PAUSE, duration);
803 size_t heapAliveSize = sHeap_->GetHeapObjectSize();
804 SetRecordData(RecordData::SHARED_ALIVE_SIZE, heapAliveSize);
805 IncreaseRecordData(RecordData::SHARED_TOTAL_ALIVE, heapAliveSize);
806
807 IncreaseTotalDuration(scopeDuration_[Scope::ScopeId::TotalGC]);
808 IncreaseAccumulatedFreeSize(GetRecordData(RecordData::START_OBJ_SIZE) -
809 GetRecordData(RecordData::END_OBJ_SIZE));
810 ProcessAfterLongGCStats();
811 }
812
ProcessAfterLongGCStats()813 void SharedGCStats::ProcessAfterLongGCStats()
814 {
815 LongGCStats *longGCStats = GetLongGCStats();
816 float gcTotalTime = GetScopeDuration(GCStats::Scope::ScopeId::TotalGC);
817 if (IsLongGC(reason_, sHeap_->InSensitiveStatus(), sHeap_->IsInBackground(), gcTotalTime)) {
818 longGCStats->SetGCType(static_cast<int>(gcType_));
819 longGCStats->SetGCReason(static_cast<int>(reason_));
820 longGCStats->SetGCIsSensitive(sHeap_->InSensitiveStatus());
821 longGCStats->SetGCIsInBackground(sHeap_->IsInBackground());
822 longGCStats->SetGCTotalTime(gcTotalTime);
823 longGCStats->SetGCMarkTime(GetScopeDuration(GCStats::Scope::ScopeId::Mark));
824 longGCStats->SetAfterGCTotalMemUsed(sHeap_->GetHeapObjectSize());
825 longGCStats->SetAfterGCTotalMemCommitted(sHeap_->GetCommittedSize());
826 longGCStats->SetAfterGCOldMemUsed(sHeap_->GetOldSpace()->GetHeapObjectSize());
827 longGCStats->SetAfterGCOldMemCommitted(sHeap_->GetOldSpace()->GetCommittedSize());
828 longGCStats->SetAfterGCHugeMemUsed(sHeap_->GetHugeObjectSpace()->GetHeapObjectSize());
829 longGCStats->SetAfterGCHugeMemCommitted(sHeap_->GetHugeObjectSpace()->GetCommittedSize());
830 longGCStats->SetAfterGCNativeBindingSize(sHeap_->GetNativeSizeAfterLastGC());
831 longGCStats->SetAfterGCNativeLimit(sHeap_->GetNativeSizeTriggerSharedGC());
832 }
833 }
834
ProcessBeforeLongGCStats()835 void SharedGCStats::ProcessBeforeLongGCStats()
836 {
837 LongGCStats *longGCStats = GetLongGCStats();
838 longGCStats->SetBeforeGCTotalMemUsed(sHeap_->GetHeapObjectSize());
839 longGCStats->SetBeforeGCTotalMemCommitted(sHeap_->GetCommittedSize());
840 longGCStats->SetBeforeGCOldMemUsed(sHeap_->GetOldSpace()->GetHeapObjectSize());
841 longGCStats->SetBeforeGCOldMemCommitted(sHeap_->GetOldSpace()->GetCommittedSize());
842 longGCStats->SetBeforeGCHugeMemUsed(sHeap_->GetHugeObjectSpace()->GetHeapObjectSize());
843 longGCStats->SetBeforeGCHugeMemCommitted(sHeap_->GetHugeObjectSpace()->GetCommittedSize());
844 longGCStats->SetBeforeGCNativeBindingSize(sHeap_->GetNativeSizeAfterLastGC());
845 longGCStats->SetBeforeGCNativeLimit(sHeap_->GetNativeSizeTriggerSharedGC());
846 }
847 } // namespace panda::ecmascript
848