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