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