• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 #ifndef PANDA_RUNTIME_MEM_GC_GC_STATS_H
16 #define PANDA_RUNTIME_MEM_GC_GC_STATS_H
17 
18 #include "libpandabase/os/mutex.h"
19 #include "runtime/include/histogram-inl.h"
20 #include "runtime/include/mem/panda_containers.h"
21 #include "runtime/include/mem/panda_string.h"
22 #include "runtime/include/time_utils.h"
23 #include "runtime/mem/gc/gc_types.h"
24 
25 #include <algorithm>
26 #include <atomic>
27 #include <ratio>
28 
29 namespace panda::mem {
30 
31 namespace test {
32 class MemStatsGenGCTest;
33 }  // namespace test
34 
35 class GCStats;
36 class HeapManager;
37 
38 enum class ObjectTypeStats : size_t {
39     YOUNG_FREED_OBJECTS = 0,
40     MOVED_OBJECTS,
41     ALL_FREED_OBJECTS,
42 
43     OBJECT_TYPE_STATS_LAST
44 };
45 
ToIndex(ObjectTypeStats type)46 constexpr size_t ToIndex(ObjectTypeStats type)
47 {
48     return static_cast<size_t>(type);
49 }
50 
51 constexpr size_t OBJECT_TYPE_STATS_SIZE = static_cast<size_t>(ObjectTypeStats::OBJECT_TYPE_STATS_LAST);
52 
53 enum class MemoryTypeStats : size_t {
54     YOUNG_FREED_BYTES = 0,
55     MOVED_BYTES,
56     ALL_FREED_BYTES,
57 
58     MEMORY_TYPE_STATS_LAST
59 };
60 
ToIndex(MemoryTypeStats type)61 constexpr size_t ToIndex(MemoryTypeStats type)
62 {
63     return static_cast<size_t>(type);
64 }
65 
66 constexpr size_t MEMORY_TYPE_STATS_SIZE = static_cast<size_t>(MemoryTypeStats::MEMORY_TYPE_STATS_LAST);
67 
68 enum class TimeTypeStats : size_t {
69     YOUNG_PAUSED_TIME = 0,
70     YOUNG_TOTAL_TIME,
71     ALL_PAUSED_TIME,
72     ALL_TOTAL_TIME,
73 
74     TIME_TYPE_STATS_LAST
75 };
76 
ToIndex(TimeTypeStats type)77 constexpr size_t ToIndex(TimeTypeStats type)
78 {
79     return static_cast<size_t>(type);
80 }
81 
82 constexpr size_t TIME_TYPE_STATS_SIZE = static_cast<size_t>(TimeTypeStats::TIME_TYPE_STATS_LAST);
83 
84 // scoped specific for GC Stats
85 class GCInstanceStats {
86 public:
GCInstanceStats()87     GCInstanceStats()
88     {
89         std::fill(begin(objects_stats_), end(objects_stats_),
90                   SimpleHistogram<uint64_t>(helpers::ValueType::VALUE_TYPE_OBJECT));
91         std::fill(begin(memory_stats_), end(memory_stats_),
92                   SimpleHistogram<uint64_t>(helpers::ValueType::VALUE_TYPE_MEMORY));
93         std::fill(begin(time_stats_), end(time_stats_), SimpleHistogram<uint64_t>(helpers::ValueType::VALUE_TYPE_TIME));
94     }
95 
AddObjectsValue(uint64_t value,ObjectTypeStats memory_type)96     void AddObjectsValue(uint64_t value, ObjectTypeStats memory_type)
97     {
98         auto index = static_cast<size_t>(memory_type);
99         objects_stats_[index].AddValue(value);
100     }
101 
AddMemoryValue(uint64_t value,MemoryTypeStats memory_type)102     void AddMemoryValue(uint64_t value, MemoryTypeStats memory_type)
103     {
104         auto index = static_cast<size_t>(memory_type);
105         memory_stats_[index].AddValue(value);
106     }
107 
AddTimeValue(uint64_t value,TimeTypeStats time_type)108     void AddTimeValue(uint64_t value, TimeTypeStats time_type)
109     {
110         auto index = static_cast<size_t>(time_type);
111         time_stats_[index].AddValue(value);
112     }
113 
AddReclaimRatioValue(double value)114     void AddReclaimRatioValue(double value)
115     {
116         reclaim_bytes_.AddValue(value);
117     }
118 
AddCopiedRatioValue(double value)119     void AddCopiedRatioValue(double value)
120     {
121         copied_bytes_.AddValue(value);
122     }
123 
124     PandaString GetDump(GCType gc_type);
125 
126     virtual ~GCInstanceStats() = default;
127 
128     NO_COPY_SEMANTIC(GCInstanceStats);
129     NO_MOVE_SEMANTIC(GCInstanceStats);
130 
131 private:
132     PandaString GetYoungSpaceDump(GCType gc_type);
133     PandaString GetAllSpacesDump(GCType gc_type);
134     std::array<SimpleHistogram<uint64_t>, OBJECT_TYPE_STATS_SIZE> objects_stats_;
135     std::array<SimpleHistogram<uint64_t>, MEMORY_TYPE_STATS_SIZE> memory_stats_;
136     std::array<SimpleHistogram<uint64_t>, TIME_TYPE_STATS_SIZE> time_stats_;
137     SimpleHistogram<double> reclaim_bytes_;
138     SimpleHistogram<double> copied_bytes_;
139 };
140 
141 // scoped all field GCStats except pause_
142 class GCScopedStats {
143 public:
144     explicit GCScopedStats(GCStats *stats, GCInstanceStats *instance_stats = nullptr);
145 
146     NO_COPY_SEMANTIC(GCScopedStats);
147     NO_MOVE_SEMANTIC(GCScopedStats);
148 
149     ~GCScopedStats();
150 
151 private:
152     uint64_t start_time_;
153     GCInstanceStats *instance_stats_;
154     GCStats *stats_;
155 };
156 
157 // scoped field GCStats while GC in pause
158 class GCScopedPauseStats {
159 public:
160     explicit GCScopedPauseStats(GCStats *stats, GCInstanceStats *instance_stats = nullptr);
161 
162     NO_COPY_SEMANTIC(GCScopedPauseStats);
163     NO_MOVE_SEMANTIC(GCScopedPauseStats);
164 
165     ~GCScopedPauseStats();
166 
167 private:
168     uint64_t start_time_;
169     GCInstanceStats *instance_stats_;
170     GCStats *stats_;
171 };
172 
173 class GCStats {
174 public:
175     explicit GCStats(MemStatsType *mem_stats, GCType gc_type_from_runtime, InternalAllocatorPtr allocator);
176     ~GCStats();
177 
178     NO_COPY_SEMANTIC(GCStats);
179     NO_MOVE_SEMANTIC(GCStats);
180 
181     PandaString GetStatistics();
182 
183     PandaString GetFinalStatistics(HeapManager *heap_manager);
184 
GetObjectsFreedBytes()185     size_t GetObjectsFreedBytes()
186     {
187 #ifdef PANDA_TARGET_64
188         static_assert(sizeof(objects_freed_bytes_) == sizeof(std::atomic_uint64_t));
189         // Atomic with seq_cst order reason: data race with objects_freed_bytes_ with requirement for sequentially
190         // consistent order where threads observe all modifications in the same order
191         return reinterpret_cast<std::atomic_uint64_t *>(&objects_freed_bytes_)->load(std::memory_order_seq_cst);
192 #endif
193 #ifdef PANDA_TARGET_32
194         static_assert(sizeof(objects_freed_bytes_) == sizeof(std::atomic_uint32_t));
195         // Atomic with seq_cst order reason: data race with objects_freed_bytes_ with requirement for sequentially
196         // consistent order where threads observe all modifications in the same order
197         return reinterpret_cast<std::atomic_uint32_t *>(&objects_freed_bytes_)->load(std::memory_order_seq_cst);
198 #endif
199         UNREACHABLE();
200     }
201 
GetObjectsFreedCount()202     uint64_t GetObjectsFreedCount()
203     {
204         return objects_freed_;
205     }
206 
GetLargeObjectsFreedBytes()207     uint64_t GetLargeObjectsFreedBytes()
208     {
209         return large_objects_freed_bytes_;
210     }
211 
GetLargeObjectsFreedCount()212     uint64_t GetLargeObjectsFreedCount()
213     {
214         return large_objects_freed_;
215     }
216 
217     void StartMutatorLock();
218     void StopMutatorLock();
219 
220 private:
221     // For convert from nano to 10 seconds
222     using PERIOD = std::deca;
223     GCType gc_type_ {GCType::INVALID_GC};
224     size_t objects_freed_ {0};
225     size_t objects_freed_bytes_ {0};
226     size_t large_objects_freed_ {0};
227     size_t large_objects_freed_bytes_ {0};
228     uint64_t start_time_ {0};
GUARDED_BY(mutator_stats_lock_)229     size_t count_mutator_ GUARDED_BY(mutator_stats_lock_) {0};
GUARDED_BY(mutator_stats_lock_)230     uint64_t mutator_start_time_ GUARDED_BY(mutator_stats_lock_) {0};
231 
232     uint64_t last_duration_ {0};
233     uint64_t total_duration_ {0};
234     uint64_t last_pause_ {0};
235     uint64_t total_pause_ {0};
GUARDED_BY(mutator_stats_lock_)236     uint64_t total_mutator_pause_ GUARDED_BY(mutator_stats_lock_) {0};
237 
238     uint64_t last_start_duration_ {0};
239     // GC in the last PERIOD
240     uint64_t count_gc_period_ {0};
241     // GC number of times every PERIOD
242     PandaVector<uint64_t> *all_number_durations_ {nullptr};
243 
244     os::memory::Mutex mutator_stats_lock_;
245     MemStatsType *mem_stats_;
246 
247     void StartCollectStats();
248     void StopCollectStats(GCInstanceStats *instance_stats);
249 
250     void RecordPause(uint64_t pause, GCInstanceStats *instance_stats);
251     void RecordDuration(uint64_t duration, GCInstanceStats *instance_stats);
252 
253     uint64_t ConvertTimeToPeriod(uint64_t time_in_nanos, bool ceil = false);
254 
255     InternalAllocatorPtr allocator_ {nullptr};
256 
257     friend GCScopedPauseStats;
258     friend GCScopedStats;
259     friend test::MemStatsGenGCTest;
260 };
261 
262 }  // namespace panda::mem
263 
264 #endif  // PANDA_RUNTIME_MEM_GC_GC_STATS_H
265