• 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, " << 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