• 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 
GetAvgSurvivalRate()106     double GetAvgSurvivalRate()
107     {
108         double copiedRate = double(GetRecordData(RecordData::YOUNG_TOTAL_ALIVE)) /
109                             GetRecordData(RecordData::YOUNG_TOTAL_COMMIT);
110         double promotedRate = double(GetRecordData(RecordData::YOUNG_TOTAL_PROMOTE)) /
111                               GetRecordData(RecordData::YOUNG_TOTAL_COMMIT);
112         return std::min(copiedRate + promotedRate, 1.0);
113     }
114 
115     void RecordGCSpeed();
116     void RecordStatisticBeforeGC(TriggerGCType gcType, GCReason reason);
117     void RecordStatisticAfterGC();
118 
119     class Scope : public ClockScope {
120     public:
121         enum ScopeId : uint8_t {
122 #define DEFINE_SCOPE(scope) scope,
123             SCOPE_LIST(DEFINE_SCOPE)
124 #undef DEFINE_SCOPE
125             SCOPE_NUM,
126         };
127 
Scope(ScopeId id,GCStats * stats)128         Scope(ScopeId id, GCStats* stats) : id_(id), stats_(stats)
129         {
130             if (id_ == ScopeId::ConcurrentMark) {
131                 stats_->NotifyConcurrentMark();
132             }
133         }
~Scope()134         ~Scope()
135         {
136             float duration = stats_->PrintTimeMilliseconds(stats_->TimeToMicroseconds(GetPauseTime()));
137             stats_->SetScopeId(id_, duration);
138         }
139 
140     private:
141         ScopeId id_;
142         GCStats* stats_;
143     };
144 
145 private:
146     bool CheckIfNeedPrint(GCType type);
147     void PrintVerboseGCStatistic();
148     void PrintGCDurationStatistic();
149     void PrintGCSummaryStatistic(GCType type = GCType::START);
150     GCType GetGCType(TriggerGCType gcType);
151     const char *GCReasonToString();
152     void InitializeRecordList();
153     const char *GetGCTypeName();
154     float GetConcurrrentMarkDuration();
155 
GetRecordDurationIndex(RecordDuration durationIdx)156     int GetRecordDurationIndex(RecordDuration durationIdx)
157     {
158         return (int)durationIdx - (int)RecordDuration::FIRST_DATA;
159     }
160 
GetRecordDuration(RecordDuration durationIdx)161     float GetRecordDuration(RecordDuration durationIdx)
162     {
163         return recordDuration_[GetRecordDurationIndex(durationIdx)];
164     }
165 
SetRecordDuration(RecordDuration durationIdx,float value)166     void SetRecordDuration(RecordDuration durationIdx, float value)
167     {
168         recordDuration_[GetRecordDurationIndex(durationIdx)] = value;
169     }
170 
IncreaseRecordDuration(RecordDuration durationIdx,float value)171     void IncreaseRecordDuration(RecordDuration durationIdx, float value)
172     {
173         recordDuration_[GetRecordDurationIndex(durationIdx)] += value;
174     }
175 
GetRecordDataIndex(RecordData dataIdx)176     int GetRecordDataIndex(RecordData dataIdx)
177     {
178         return (int)dataIdx - (int)RecordData::FIRST_DATA;
179     }
180 
181     void IncreaseRecordData(RecordData dataIdx, size_t value = 1)
182     {
183         recordData_[GetRecordDataIndex(dataIdx)] += value;
184     }
185 
SetScopeId(int pos,float duration)186     void SetScopeId(int pos, float duration)
187     {
188         scopeDuration_[pos] = duration;
189     }
190 
NotifyConcurrentMark()191     void NotifyConcurrentMark()
192     {
193         concurrentMark_ = true;
194     }
195 
TimeToMicroseconds(Duration time)196     size_t TimeToMicroseconds(Duration time)
197     {
198         return std::chrono::duration_cast<std::chrono::microseconds>(time).count();
199     }
200 
PrintTimeMilliseconds(uint64_t ms)201     float PrintTimeMilliseconds(uint64_t ms)
202     {
203         return (float)ms / THOUSAND;
204     }
205 
sizeToMB(size_t size)206     float sizeToMB(size_t size)
207     {
208         return (float)size / 1_MB;
209     }
210 
sizeToKB(size_t size)211     float sizeToKB(size_t size)
212     {
213         return (float)size / 1_KB;
214     }
215 
216     const Heap *heap_ {nullptr};
217     size_t longPauseTime_ = 0;
218 
219     static constexpr size_t DEFAULT_UPDATE_REFERENCE_SPEED = 10_MB;
220     static constexpr size_t DEFAULT_OLD_CLEAR_NATIVE_OBJ_SPEED = 1_KB;
221     static constexpr size_t DEFAULT_OLD_EVACUATE_SPACE_SPEED = 600_KB;
222     static constexpr size_t DEFAULT_YOUNG_CLEAR_NATIVE_OBJ_SPEED = 3_KB;
223 
224     GCType gcType_ {GCType::START};
225     GCReason reason_ {GCReason::OTHER};
226     float scopeDuration_[Scope::ScopeId::SCOPE_NUM] {0.0f};
227     size_t recordData_[(uint8_t)RecordData::NUM_OF_DATA];
228     size_t gcSpeed_ [(uint8_t)SpeedData::NUM_OF_SPEED] = {
229         DEFAULT_UPDATE_REFERENCE_SPEED, DEFAULT_OLD_CLEAR_NATIVE_OBJ_SPEED,
230         DEFAULT_OLD_EVACUATE_SPACE_SPEED, DEFAULT_YOUNG_CLEAR_NATIVE_OBJ_SPEED};
231     float recordDuration_[(uint8_t)RecordDuration::NUM_OF_DURATION] {0.0f};
232     bool concurrentMark_ {false};
233 
234     static constexpr uint32_t THOUSAND = 1000;
235 
236     NO_COPY_SEMANTIC(GCStats);
237     NO_MOVE_SEMANTIC(GCStats);
238 };
239 }  // namespace panda::ecmascript
240 
241 #endif  // ECMASCRIPT_MEM_GC_STATS_H
242