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::PARTIAL_EDEN_GC);
35 PrintGCSummaryStatistic(GCType::PARTIAL_YOUNG_GC);
36 PrintGCSummaryStatistic(GCType::PARTIAL_OLD_GC);
37 PrintGCSummaryStatistic(GCType::COMPRESS_GC);
38 PrintGCMemoryStatistic();
39 }
40
PrintGCStatistic()41 void 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
GCReasonToString()64 const char *GCStats::GCReasonToString()
65 {
66 return GCReasonToString(reason_);
67 }
68
GCReasonToString(GCReason reason)69 const 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
GetConcurrrentMarkDuration()99 float GCStats::GetConcurrrentMarkDuration()
100 {
101 return concurrentMark_ ? scopeDuration_[Scope::ScopeId::ConcurrentMark] : 0;
102 }
103
PrintVerboseGCStatistic()104 void GCStats::PrintVerboseGCStatistic()
105 {
106 PrintGCDurationStatistic();
107 PrintGCMemoryStatistic();
108 PrintGCSummaryStatistic();
109 }
110
PrintGCMemoryStatistic()111 void 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
PrintGCDurationStatistic()210 void 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
CheckIfNeedPrint(GCType type)277 bool 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
PrintGCSummaryStatistic(GCType type)303 void GCStats::PrintGCSummaryStatistic(GCType type)
304 {
305 if (type != GCType::START && !CheckIfNeedPrint(type)) {
306 return;
307 } else {
308 type = type == GCType::START ? gcType_ : type;
309 }
310 LOG_GC(INFO) << "/***************** GC summary statistic: *****************/";
311 switch (type) {
312 case GCType::PARTIAL_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
GetAccumulatedAllocateSize()388 size_t GCStats::GetAccumulatedAllocateSize()
389 {
390 return accumulatedFreeSize_ + heap_->GetHeapObjectSize();
391 }
392
RecordStatisticBeforeGC(TriggerGCType gcType, GCReason reason)393 void 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
RecordStatisticAfterGC()434 void 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
RecordGCSpeed()528 void 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
GetGCType(TriggerGCType gcType)582 GCType 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
InitializeRecordList()614 void GCStats::InitializeRecordList()
615 {
616 for (float &duration : scopeDuration_) {
617 duration = 0.0f;
618 }
619 concurrentMark_ = false;
620 }
621
CheckIfLongTimePause()622 bool 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
PrintStatisticResult()631 void SharedGCStats::PrintStatisticResult()
632 {
633 LOG_GC(INFO) << "/******************* SharedGCStats statistic: *******************/";
634 PrintSharedGCSummaryStatistic();
635 PrintGCMemoryStatistic();
636 }
637
PrintGCStatistic()638 void 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
PrintSharedGCSummaryStatistic()654 void 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
PrintGCMemoryStatistic()671 void 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
PrintSharedGCDuration()707 void 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
GetAccumulatedAllocateSize()725 size_t SharedGCStats::GetAccumulatedAllocateSize()
726 {
727 return accumulatedFreeSize_ + sHeap_->GetHeapObjectSize();
728 }
729
RecordStatisticBeforeGC(TriggerGCType gcType, GCReason reason)730 void 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
RecordStatisticAfterGC()741 void 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