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