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 "ecmascript/mem/heap.h"
19 #include "ecmascript/mem/mem.h"
20
21 namespace panda::ecmascript {
PrintStatisticResult(bool isForce)22 void GCStats::PrintStatisticResult(bool isForce)
23 {
24 LOG(INFO, RUNTIME) << "/******************* GCStats statistic: *******************/";
25 PrintSemiStatisticResult(isForce);
26 PrintMixStatisticResult(isForce);
27 PrintCompressStatisticResult(isForce);
28 PrintHeapStatisticResult(isForce);
29 }
30
PrintSemiStatisticResult(bool isForce)31 void GCStats::PrintSemiStatisticResult(bool isForce)
32 {
33 if ((isForce && semiGCCount_ != 0) || (!isForce && semiGCCount_ != lastSemiGCCount_)) {
34 lastSemiGCCount_ = semiGCCount_;
35 LOG(INFO, RUNTIME) << " STWYoungGC statistic: total semi gc count " << semiGCCount_;
36 LOG(INFO, RUNTIME) << " MIN pause time: " << PrintTimeMilliseconds(semiGCMinPause_) << "ms"
37 << " MAX pause time: " << PrintTimeMilliseconds(semiGCMAXPause_) << "ms"
38 << " total pause time: " << PrintTimeMilliseconds(semiGCTotalPause_) << "ms"
39 << " average pause time: " << PrintTimeMilliseconds(semiGCTotalPause_ / semiGCCount_)
40 << "ms"
41 << " tatal alive size: " << sizeToMB(semiTotalAliveSize_) << "MB"
42 << " average alive size: " << sizeToMB(semiTotalAliveSize_ / semiGCCount_) << "MB"
43 << " tatal commit size: " << sizeToMB(semiTotalCommitSize_) << "MB"
44 << " average commit size: " << sizeToMB(semiTotalCommitSize_ / semiGCCount_) << "MB"
45 << " semi aliveRate: " << double(semiTotalAliveSize_) / semiTotalCommitSize_
46 << " total promote size: " << sizeToMB(semiTotalPromoteSize_) << "MB"
47 << " average promote size: " << sizeToMB(semiTotalPromoteSize_ / semiGCCount_) << "MB";
48 }
49 }
50
PrintMixStatisticResult(bool isForce)51 void GCStats::PrintMixStatisticResult(bool isForce)
52 {
53 if ((isForce && mixGCCount_ != 0) || (!isForce && lastOldGCCount_ != mixGCCount_)) {
54 lastOldGCCount_ = mixGCCount_;
55 LOG(INFO, RUNTIME) << " MixGC with non-concurrent mark statistic: total old gc count " << mixGCCount_;
56 LOG(INFO, RUNTIME) << " Pause time statistic:: MIN pause time: " << PrintTimeMilliseconds(mixGCMinPause_)
57 << "ms"
58 << " MAX pause time: " << PrintTimeMilliseconds(mixGCMAXPause_) << "ms"
59 << " total pause time: " << PrintTimeMilliseconds(mixGCTotalPause_) << "ms"
60 << " average pause time: " << PrintTimeMilliseconds(mixGCTotalPause_ / mixGCCount_) << "ms";
61 if (!isForce) {
62 PrintHeapStatisticResult(true);
63 }
64 }
65
66 if ((isForce && mixConcurrentMarkGCCount_ != 0) ||
67 (!isForce && lastOldConcurrentMarkGCCount_ != mixConcurrentMarkGCCount_)) {
68 lastOldConcurrentMarkGCCount_ = mixConcurrentMarkGCCount_;
69 LOG(INFO, RUNTIME) << " MixCollector with concurrent mark statistic: total old gc count "
70 << mixConcurrentMarkGCCount_;
71 LOG(INFO, RUNTIME) << " Pause time statistic:: Current GC pause time: "
72 << PrintTimeMilliseconds(mixConcurrentMarkGCPauseTime_) << "ms"
73 << " Concurrent mark pause time: " << PrintTimeMilliseconds(mixConcurrentMarkMarkPause_)
74 << "ms"
75 << " Concurrent mark wait time: " << PrintTimeMilliseconds(mixConcurrentMarkWaitPause_)
76 << "ms"
77 << " Remark pause time: " << PrintTimeMilliseconds(mixConcurrentMarkRemarkPause_) << "ms"
78 << " Evacuate pause time: " << PrintTimeMilliseconds(mixConcurrentMarkEvacuatePause_)
79 << "ms"
80 << " MIN pause time: " << PrintTimeMilliseconds(mixConcurrentMarkGCMinPause_) << "ms"
81 << " MAX pause time: " << PrintTimeMilliseconds(mixConcurrentMarkGCMAXPause_) << "ms"
82 << " total pause time: " << PrintTimeMilliseconds(mixConcurrentMarkGCTotalPause_) << "ms"
83 << " average pause time: "
84 << PrintTimeMilliseconds(mixConcurrentMarkGCTotalPause_ / mixConcurrentMarkGCCount_)
85 << "ms";
86 if (!isForce) {
87 PrintHeapStatisticResult(true);
88 }
89 }
90 }
91
PrintCompressStatisticResult(bool isForce)92 void GCStats::PrintCompressStatisticResult(bool isForce)
93 {
94 if ((isForce && fullGCCount_ != 0) || (!isForce && fullGCCount_ != lastFullGCCount_)) {
95 lastFullGCCount_ = fullGCCount_;
96 LOG(INFO, RUNTIME) << " FullGC statistic: total compress gc count " << fullGCCount_;
97 LOG(INFO, RUNTIME)
98 << " MIN pause time: " << PrintTimeMilliseconds(fullGCMinPause_) << "ms"
99 << " MAX pause time: " << PrintTimeMilliseconds(fullGCMaxPause_) << "ms"
100 << " total pause time: " << PrintTimeMilliseconds(fullGCTotalPause_) << "ms"
101 << " average pause time: " << PrintTimeMilliseconds(fullGCTotalPause_ / fullGCCount_) << "ms"
102 << " young and old total alive size: " << sizeToMB(compressYoungAndOldAliveSize_) << "MB"
103 << " young and old average alive size: " << sizeToMB(compressYoungAndOldAliveSize_ / fullGCCount_)
104 << "MB"
105 << " young total commit size: " << sizeToMB(compressYoungCommitSize_) << "MB"
106 << " old total commit size: " << sizeToMB(compressOldCommitSize_) << "MB"
107 << " young and old average commit size: "
108 << sizeToMB((compressYoungCommitSize_ + compressOldCommitSize_) / fullGCCount_) << "MB"
109 << " young and old free rate: "
110 << 1 - float(compressYoungAndOldAliveSize_) / (compressYoungCommitSize_ + compressOldCommitSize_)
111 << " non move total free size: " << sizeToMB(compressNonMoveTotalFreeSize_) << "MB"
112 << " non move total commit size: " << sizeToMB(compressNonMoveTotalCommitSize_) << "MB"
113 << " non move free rate: " << float(compressNonMoveTotalFreeSize_) / compressNonMoveTotalCommitSize_;
114 }
115 }
116
PrintHeapStatisticResult(bool isForce)117 void GCStats::PrintHeapStatisticResult(bool isForce)
118 {
119 if (isForce && heap_ != nullptr) {
120 NativeAreaAllocator *nativeAreaAllocator = const_cast<NativeAreaAllocator *>(heap_->GetNativeAreaAllocator());
121 HeapRegionAllocator *heapRegionAllocator = const_cast<HeapRegionAllocator *>(heap_->GetHeapRegionAllocator());
122 LOG(INFO, RUNTIME) << "/******************* Memory statistic: *******************/";
123 LOG(INFO, RUNTIME) << " Anno memory usage size:" << sizeToMB(heapRegionAllocator->GetAnnoMemoryUsage())
124 << "MB"
125 << " anno memory max usage size:" << sizeToMB(heapRegionAllocator->GetMaxAnnoMemoryUsage())
126 << "MB"
127 << " native memory usage size:" << sizeToMB(nativeAreaAllocator->GetNativeMemoryUsage())
128 << "MB"
129 << " native memory max usage size:"
130 << sizeToMB(nativeAreaAllocator->GetMaxNativeMemoryUsage()) << "MB";
131 LOG(INFO, RUNTIME) << " Semi space commit size" << sizeToMB(heap_->GetNewSpace()->GetCommittedSize()) << "MB"
132 << " semi space heap object size: " << sizeToMB(heap_->GetNewSpace()->GetHeapObjectSize())
133 << "MB"
134 << " old space commit size: "
135 << sizeToMB(heap_->GetOldSpace()->GetCommittedSize()) << "MB"
136 << " old space heap object size: " << sizeToMB(heap_->GetOldSpace()->GetHeapObjectSize())
137 << "MB"
138 << " non move space commit size: "
139 << sizeToMB(heap_->GetNonMovableSpace()->GetCommittedSize()) << "MB"
140 << " huge object space commit size: "
141 << sizeToMB(heap_->GetHugeObjectSpace()->GetCommittedSize()) << "MB";
142 }
143 }
144
StatisticSTWYoungGC(Duration time,size_t aliveSize,size_t promoteSize,size_t commitSize)145 void GCStats::StatisticSTWYoungGC(Duration time, size_t aliveSize, size_t promoteSize, size_t commitSize)
146 {
147 auto timeToMillion = TimeToMicroseconds(time);
148 if (semiGCCount_ == 0) {
149 semiGCMinPause_ = timeToMillion;
150 semiGCMAXPause_ = timeToMillion;
151 } else {
152 semiGCMinPause_ = std::min(semiGCMinPause_, timeToMillion);
153 semiGCMAXPause_ = std::max(semiGCMAXPause_, timeToMillion);
154 }
155 semiGCTotalPause_ += timeToMillion;
156 semiTotalAliveSize_ += aliveSize;
157 semiTotalCommitSize_ += commitSize;
158 semiTotalPromoteSize_ += promoteSize;
159 semiGCCount_++;
160 }
161
StatisticMixGC(bool concurrentMark,Duration time,size_t freeSize)162 void GCStats::StatisticMixGC(bool concurrentMark, Duration time, size_t freeSize)
163 {
164 auto timeToMillion = TimeToMicroseconds(time);
165 if (concurrentMark) {
166 timeToMillion += mixConcurrentMarkMarkPause_;
167 timeToMillion += mixConcurrentMarkWaitPause_;
168 if (mixConcurrentMarkGCCount_ == 0) {
169 mixConcurrentMarkGCMinPause_ = timeToMillion;
170 mixConcurrentMarkGCMAXPause_ = timeToMillion;
171 } else {
172 mixConcurrentMarkGCMinPause_ = std::min(mixConcurrentMarkGCMinPause_, timeToMillion);
173 mixConcurrentMarkGCMAXPause_ = std::max(mixConcurrentMarkGCMAXPause_, timeToMillion);
174 }
175 mixConcurrentMarkGCPauseTime_ = timeToMillion;
176 mixConcurrentMarkGCTotalPause_ += timeToMillion;
177 mixOldSpaceConcurrentMarkFreeSize_ = freeSize;
178 mixConcurrentMarkGCCount_++;
179 } else {
180 if (mixGCCount_ == 0) {
181 mixGCMinPause_ = timeToMillion;
182 mixGCMAXPause_ = timeToMillion;
183 } else {
184 mixGCMinPause_ = std::min(mixGCMinPause_, timeToMillion);
185 mixGCMAXPause_ = std::max(mixGCMAXPause_, timeToMillion);
186 }
187 mixGCTotalPause_ += timeToMillion;
188 mixOldSpaceFreeSize_ = freeSize;
189 mixGCCount_++;
190 }
191 }
192
StatisticFullGC(Duration time,size_t youngAndOldAliveSize,size_t youngCommitSize,size_t oldCommitSize,size_t nonMoveSpaceFreeSize,size_t nonMoveSpaceCommitSize)193 void GCStats::StatisticFullGC(Duration time, size_t youngAndOldAliveSize, size_t youngCommitSize,
194 size_t oldCommitSize, size_t nonMoveSpaceFreeSize,
195 size_t nonMoveSpaceCommitSize)
196 {
197 auto timeToMillion = TimeToMicroseconds(time);
198 if (fullGCCount_ == 0) {
199 fullGCMinPause_ = timeToMillion;
200 fullGCMaxPause_ = timeToMillion;
201 } else {
202 fullGCMinPause_ = std::min(fullGCMinPause_, timeToMillion);
203 fullGCMaxPause_ = std::max(fullGCMaxPause_, timeToMillion);
204 }
205 fullGCTotalPause_ += timeToMillion;
206 compressYoungAndOldAliveSize_ += youngAndOldAliveSize;
207 compressYoungCommitSize_ += youngCommitSize;
208 compressOldCommitSize_ += oldCommitSize;
209 compressNonMoveTotalFreeSize_ += nonMoveSpaceFreeSize;
210 compressNonMoveTotalCommitSize_ += nonMoveSpaceCommitSize;
211 fullGCCount_++;
212 }
213
StatisticConcurrentMark(Duration time)214 void GCStats::StatisticConcurrentMark(Duration time)
215 {
216 mixConcurrentMarkMarkPause_ = TimeToMicroseconds(time);
217 }
218
StatisticConcurrentMarkWait(Duration time)219 void GCStats::StatisticConcurrentMarkWait(Duration time)
220 {
221 mixConcurrentMarkWaitPause_ = TimeToMicroseconds(time);
222 }
223
StatisticConcurrentEvacuate(Duration time)224 void GCStats::StatisticConcurrentEvacuate(Duration time)
225 {
226 mixConcurrentMarkEvacuatePause_ = TimeToMicroseconds(time);
227 }
228
StatisticConcurrentRemark(Duration time)229 void GCStats::StatisticConcurrentRemark(Duration time)
230 {
231 mixConcurrentMarkRemarkPause_ = TimeToMicroseconds(time);
232 }
233 } // namespace panda::ecmascript
234