• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_MEM_GC_STATS_H
17 #define ECMASCRIPT_MEM_GC_STATS_H
18 
19 #include <chrono>
20 #include <cstring>
21 #include <ctime>
22 
23 #include "ecmascript/common.h"
24 #include "ecmascript/mem/clock_scope.h"
25 #include "ecmascript/mem/mem_common.h"
26 #include "libpandabase/macros.h"
27 
28 namespace panda::ecmascript {
29 class Heap;
30 
31 enum class GCType : int {
32     STW_YOUNG_GC = 0,
33     PARTIAL_YOUNG_GC,
34     PARTIAL_OLD_GC,
35     COMPRESS_GC,
36     OTHER,
37     START,
38 };
39 
40 enum class RecordData : uint8_t {
41 #define DEFINE_SCOPE(scope) scope,
42     RECORD_DATA(DEFINE_SCOPE)
43 #undef DEFINE_SCOPE
44     NUM_OF_DATA,
45     FIRST_DATA = START_OBJ_SIZE,
46     END_RECORD_OVERWRITE = COLLECT_REGION_SET_SIZE,
47 };
48 
49 enum class SpeedData : uint8_t {
50 #define DEFINE_SCOPE(scope) scope,
51     TRACE_GC_SPEED(DEFINE_SCOPE)
52 #undef DEFINE_SCOPE
53     NUM_OF_SPEED,
54 };
55 
56 enum class RecordDuration : uint8_t {
57 #define DEFINE_SCOPE(scope) scope,
58     RECORD_DURATION(DEFINE_SCOPE)
59 #undef DEFINE_SCOPE
60     NUM_OF_DURATION,
61     FIRST_DATA = SEMI_MIN_PAUSE,
62 };
63 
64 #define TRACE_GC(scope_id, gc_stats)    \
65     [[maybe_unused]] GCStats::Scope sp(scope_id, gc_stats)
66 
67 class GCStats {
68     using Duration = std::chrono::duration<uint64_t, std::nano>;
69 
70 public:
GCStats(const Heap * heap)71     explicit GCStats(const Heap *heap) : heap_(heap) {}
GCStats(const Heap * heap,size_t longPuaseTime)72     GCStats(const Heap *heap, size_t longPuaseTime) : heap_(heap),
73         longPauseTime_(longPuaseTime) {}
74     ~GCStats() = default;
75 
76     void PrintStatisticResult();
77     void PrintGCMemoryStatistic();
78     bool CheckIfLongTimePause();
79     void PrintGCStatistic();
80 
GetGCSpeed(SpeedData data)81     float GetGCSpeed(SpeedData data)
82     {
83         return gcSpeed_[(uint8_t)data];
84     }
85 
SetRecordData(RecordData dataIdx,size_t value)86     void SetRecordData(RecordData dataIdx, size_t value)
87     {
88         recordData_[GetRecordDataIndex(dataIdx)] = value;
89     }
90 
GetRecordData(RecordData dataIdx)91     size_t GetRecordData(RecordData dataIdx)
92     {
93         return recordData_[GetRecordDataIndex(dataIdx)];
94     }
95 
SetGCReason(GCReason reason)96     void SetGCReason(GCReason reason)
97     {
98         reason_ = reason;
99     }
100 
GetGCReason()101     GCReason GetGCReason() const
102     {
103         return reason_;
104     }
105 
GetGCTypeName()106     const char *GetGCTypeName()
107     {
108         switch (gcType_) {
109             case GCType::STW_YOUNG_GC:
110                 return "STWYoungGC";
111             case GCType::PARTIAL_YOUNG_GC:
112                 return "HPP YoungGC";
113             case GCType::PARTIAL_OLD_GC:
114                 return "HPP OldGC";
115             case GCType::COMPRESS_GC:
116                 return "CompressGC";
117             default:
118                 return "UnknownType";
119         }
120     }
121 
122     const char *GCReasonToString();
123 
GetAvgSurvivalRate()124     double GetAvgSurvivalRate()
125     {
126         double copiedRate = double(GetRecordData(RecordData::YOUNG_TOTAL_ALIVE)) /
127                             GetRecordData(RecordData::YOUNG_TOTAL_COMMIT);
128         double promotedRate = double(GetRecordData(RecordData::YOUNG_TOTAL_PROMOTE)) /
129                               GetRecordData(RecordData::YOUNG_TOTAL_COMMIT);
130         return std::min(copiedRate + promotedRate, 1.0);
131     }
132 
133     void RecordGCSpeed();
134     void RecordStatisticBeforeGC(TriggerGCType gcType, GCReason reason);
135     void RecordStatisticAfterGC();
136 
137     class Scope : public ClockScope {
138     public:
139         enum ScopeId : uint8_t {
140 #define DEFINE_SCOPE(scope) scope,
141             SCOPE_LIST(DEFINE_SCOPE)
142 #undef DEFINE_SCOPE
143             SCOPE_NUM,
144         };
145 
Scope(ScopeId id,GCStats * stats)146         Scope(ScopeId id, GCStats* stats) : id_(id), stats_(stats)
147         {
148             if (id_ == ScopeId::ConcurrentMark) {
149                 stats_->NotifyConcurrentMark();
150             }
151         }
~Scope()152         ~Scope()
153         {
154             float duration = stats_->PrintTimeMilliseconds(stats_->TimeToMicroseconds(GetPauseTime()));
155             stats_->SetScopeId(id_, duration);
156         }
157 
158     private:
159         ScopeId id_;
160         GCStats* stats_;
161     };
162 
163 private:
164     bool CheckIfNeedPrint(GCType type);
165     void PrintVerboseGCStatistic();
166     void PrintGCDurationStatistic();
167     void PrintGCSummaryStatistic(GCType type = GCType::START);
168     GCType GetGCType(TriggerGCType gcType);
169     void InitializeRecordList();
170     float GetConcurrrentMarkDuration();
171 
GetRecordDurationIndex(RecordDuration durationIdx)172     int GetRecordDurationIndex(RecordDuration durationIdx)
173     {
174         return (int)durationIdx - (int)RecordDuration::FIRST_DATA;
175     }
176 
GetRecordDuration(RecordDuration durationIdx)177     float GetRecordDuration(RecordDuration durationIdx)
178     {
179         return recordDuration_[GetRecordDurationIndex(durationIdx)];
180     }
181 
SetRecordDuration(RecordDuration durationIdx,float value)182     void SetRecordDuration(RecordDuration durationIdx, float value)
183     {
184         recordDuration_[GetRecordDurationIndex(durationIdx)] = value;
185     }
186 
IncreaseRecordDuration(RecordDuration durationIdx,float value)187     void IncreaseRecordDuration(RecordDuration durationIdx, float value)
188     {
189         recordDuration_[GetRecordDurationIndex(durationIdx)] += value;
190     }
191 
GetRecordDataIndex(RecordData dataIdx)192     int GetRecordDataIndex(RecordData dataIdx)
193     {
194         return (int)dataIdx - (int)RecordData::FIRST_DATA;
195     }
196 
197     void IncreaseRecordData(RecordData dataIdx, size_t value = 1)
198     {
199         recordData_[GetRecordDataIndex(dataIdx)] += value;
200     }
201 
SetScopeId(int pos,float duration)202     void SetScopeId(int pos, float duration)
203     {
204         scopeDuration_[pos] = duration;
205     }
206 
NotifyConcurrentMark()207     void NotifyConcurrentMark()
208     {
209         concurrentMark_ = true;
210     }
211 
TimeToMicroseconds(Duration time)212     size_t TimeToMicroseconds(Duration time)
213     {
214         return std::chrono::duration_cast<std::chrono::microseconds>(time).count();
215     }
216 
PrintTimeMilliseconds(uint64_t ms)217     float PrintTimeMilliseconds(uint64_t ms)
218     {
219         return (float)ms / THOUSAND;
220     }
221 
sizeToMB(size_t size)222     float sizeToMB(size_t size)
223     {
224         return (float)size / 1_MB;
225     }
226 
sizeToKB(size_t size)227     float sizeToKB(size_t size)
228     {
229         return (float)size / 1_KB;
230     }
231 
232     const Heap *heap_ {nullptr};
233     size_t longPauseTime_ = 0;
234 
235     static constexpr size_t DEFAULT_UPDATE_REFERENCE_SPEED = 10_MB;
236     static constexpr size_t DEFAULT_OLD_CLEAR_NATIVE_OBJ_SPEED = 1_KB;
237     static constexpr size_t DEFAULT_OLD_EVACUATE_SPACE_SPEED = 600_KB;
238     static constexpr size_t DEFAULT_YOUNG_CLEAR_NATIVE_OBJ_SPEED = 3_KB;
239 
240     GCType gcType_ {GCType::START};
241     GCReason reason_ {GCReason::OTHER};
242     float scopeDuration_[Scope::ScopeId::SCOPE_NUM] {0.0f};
243     size_t recordData_[(uint8_t)RecordData::NUM_OF_DATA];
244     size_t gcSpeed_ [(uint8_t)SpeedData::NUM_OF_SPEED] = {
245         DEFAULT_UPDATE_REFERENCE_SPEED, DEFAULT_OLD_CLEAR_NATIVE_OBJ_SPEED,
246         DEFAULT_OLD_EVACUATE_SPACE_SPEED, DEFAULT_YOUNG_CLEAR_NATIVE_OBJ_SPEED};
247     float recordDuration_[(uint8_t)RecordDuration::NUM_OF_DURATION] {0.0f};
248     bool concurrentMark_ {false};
249 
250     static constexpr uint32_t THOUSAND = 1000;
251 
252     NO_COPY_SEMANTIC(GCStats);
253     NO_MOVE_SEMANTIC(GCStats);
254 };
255 }  // namespace panda::ecmascript
256 
257 #endif  // ECMASCRIPT_MEM_GC_STATS_H
258