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