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