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 "runtime/mem/mem_stats.h"
17
18 #include "libpandabase/utils/utf.h"
19 #include "runtime/include/class.h"
20 #include "runtime/include/runtime.h"
21 #include "runtime/mem/mem_stats_additional_info.h"
22 #include "runtime/mem/mem_stats_default.h"
23 #include "runtime/mem/object_helpers.h"
24
25 namespace panda::mem {
26
27 template <typename T>
RecordAllocateObject(size_t size,SpaceType type_mem)28 void MemStats<T>::RecordAllocateObject(size_t size, SpaceType type_mem)
29 {
30 ASSERT(IsHeapSpace(type_mem));
31 RecordAllocate(size, type_mem);
32 if (type_mem == SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT) {
33 humongous_objects_allocated_.fetch_add(1, std::memory_order_acq_rel);
34 } else {
35 objects_allocated_.fetch_add(1, std::memory_order_acq_rel);
36 }
37 }
38
39 template <typename T>
RecordMovedObjects(size_t total_object_num,size_t size,SpaceType type_mem)40 void MemStats<T>::RecordMovedObjects(size_t total_object_num, size_t size, SpaceType type_mem)
41 {
42 ASSERT(IsHeapSpace(type_mem));
43 RecordMoved(size, type_mem);
44 // We can't move SPACE_TYPE_HUMONGOUS_OBJECT
45 ASSERT(type_mem != SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT);
46 uint64_t old_val = objects_allocated_.fetch_sub(total_object_num, std::memory_order_acq_rel);
47 (void)old_val;
48 ASSERT(old_val >= total_object_num);
49 }
50
51 template <typename T>
RecordFreeObject(size_t object_size,SpaceType type_mem)52 void MemStats<T>::RecordFreeObject(size_t object_size, SpaceType type_mem)
53 {
54 ASSERT(IsHeapSpace(type_mem));
55 RecordFree(object_size, type_mem);
56 if (type_mem == SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT) {
57 humongous_objects_freed_.fetch_add(1, std::memory_order_acq_rel);
58 } else {
59 objects_freed_.fetch_add(1, std::memory_order_acq_rel);
60 }
61 }
62
63 template <typename T>
RecordFreeObjects(size_t total_object_num,size_t total_object_size,SpaceType type_mem)64 void MemStats<T>::RecordFreeObjects(size_t total_object_num, size_t total_object_size, SpaceType type_mem)
65 {
66 ASSERT(IsHeapSpace(type_mem));
67 RecordFree(total_object_size, type_mem);
68 if (type_mem == SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT) {
69 humongous_objects_freed_.fetch_add(total_object_num, std::memory_order_acq_rel);
70 } else {
71 objects_freed_.fetch_add(total_object_num, std::memory_order_acq_rel);
72 }
73 }
74
75 template <typename T>
GetStatistics(HeapManager * heap_manager)76 PandaString MemStats<T>::GetStatistics(HeapManager *heap_manager)
77 {
78 PandaStringStream statistic;
79 statistic << "memory statistics:" << std::endl;
80 statistic << "heap: allocated - " << GetAllocatedHeap() << ", freed - " << GetFreedHeap() << std::endl;
81 statistic << "raw memory: allocated - " << GetAllocated(SpaceType::SPACE_TYPE_INTERNAL) << ", freed - "
82 << GetFreed(SpaceType::SPACE_TYPE_INTERNAL) << std::endl;
83 statistic << "compiler: allocated - " << GetAllocated(SpaceType::SPACE_TYPE_CODE) << std::endl;
84 statistic << "ArenaAllocator: allocated - " << GetAllocated(SpaceType::SPACE_TYPE_COMPILER) << std::endl;
85 statistic << "total footprint now - " << GetTotalFootprint() << std::endl;
86 statistic << "total allocated object - " << GetTotalObjectsAllocated() << std::endl;
87 statistic << "min GC pause time - " << GetMinGCPause() << std::endl;
88 statistic << "max GC pause time - " << GetMaxGCPause() << std::endl;
89 statistic << "average GC pause time - " << GetAverageGCPause() << std::endl;
90 statistic << "total GC pause time - " << GetTotalGCPause() << std::endl;
91 auto additional_statistics = static_cast<T *>(this)->GetAdditionalStatistics(heap_manager);
92 return statistic.str() + additional_statistics;
93 }
94
95 template <typename T>
GetTotalObjectsAllocated() const96 [[nodiscard]] uint64_t MemStats<T>::GetTotalObjectsAllocated() const
97 {
98 return objects_allocated_.load(std::memory_order_acquire);
99 }
100
101 template <typename T>
GetTotalObjectsFreed() const102 [[nodiscard]] uint64_t MemStats<T>::GetTotalObjectsFreed() const
103 {
104 return objects_freed_.load(std::memory_order_acquire);
105 }
106
107 template <typename T>
GetTotalRegularObjectsAllocated() const108 [[nodiscard]] uint64_t MemStats<T>::GetTotalRegularObjectsAllocated() const
109 {
110 return GetTotalObjectsAllocated() - GetTotalHumongousObjectsAllocated();
111 }
112
113 template <typename T>
GetTotalRegularObjectsFreed() const114 [[nodiscard]] uint64_t MemStats<T>::GetTotalRegularObjectsFreed() const
115 {
116 return GetTotalObjectsFreed() - GetTotalHumongousObjectsFreed();
117 }
118
119 template <typename T>
GetTotalHumongousObjectsAllocated() const120 [[nodiscard]] uint64_t MemStats<T>::GetTotalHumongousObjectsAllocated() const
121 {
122 return humongous_objects_allocated_.load(std::memory_order_acquire);
123 }
124
125 template <typename T>
GetTotalHumongousObjectsFreed() const126 [[nodiscard]] uint64_t MemStats<T>::GetTotalHumongousObjectsFreed() const
127 {
128 return humongous_objects_freed_.load(std::memory_order_acquire);
129 }
130
131 template <typename T>
GetObjectsCountAlive() const132 [[nodiscard]] uint64_t MemStats<T>::GetObjectsCountAlive() const
133 {
134 return GetTotalObjectsAllocated() - GetTotalObjectsFreed();
135 }
136
137 template <typename T>
GetRegularObjectsCountAlive() const138 [[nodiscard]] uint64_t MemStats<T>::GetRegularObjectsCountAlive() const
139 {
140 return GetTotalRegularObjectsAllocated() - GetTotalRegularObjectsFreed();
141 }
142
143 template <typename T>
GetHumonguousObjectsCountAlive() const144 [[nodiscard]] uint64_t MemStats<T>::GetHumonguousObjectsCountAlive() const
145 {
146 return GetTotalHumongousObjectsAllocated() - GetTotalHumongousObjectsFreed();
147 }
148
149 template <typename T>
RecordGCPauseStart()150 void MemStats<T>::RecordGCPauseStart()
151 {
152 pause_start_time_ = clock::now();
153 }
154
155 template <typename T>
RecordGCPauseEnd()156 void MemStats<T>::RecordGCPauseEnd()
157 {
158 duration pause_time = clock::now() - pause_start_time_;
159 if (pause_count_) {
160 min_pause_ = std::min(min_pause_, pause_time);
161 max_pause_ = std::max(max_pause_, pause_time);
162 } else {
163 min_pause_ = pause_time;
164 max_pause_ = pause_time;
165 }
166 pause_count_++;
167 sum_pause_ += pause_time;
168 }
169
170 template <typename T>
GetMinGCPause() const171 uint64_t MemStats<T>::GetMinGCPause() const
172 {
173 return std::chrono::duration_cast<std::chrono::milliseconds>(min_pause_).count();
174 }
175
176 template <typename T>
GetMaxGCPause() const177 uint64_t MemStats<T>::GetMaxGCPause() const
178 {
179 return std::chrono::duration_cast<std::chrono::milliseconds>(max_pause_).count();
180 }
181
182 template <typename T>
GetAverageGCPause() const183 uint64_t MemStats<T>::GetAverageGCPause() const
184 {
185 return pause_count_ ? std::chrono::duration_cast<std::chrono::milliseconds>(sum_pause_).count() / pause_count_ : 0;
186 }
187
188 template <typename T>
GetTotalGCPause() const189 uint64_t MemStats<T>::GetTotalGCPause() const
190 {
191 return std::chrono::duration_cast<std::chrono::milliseconds>(sum_pause_).count();
192 }
193
194 template class MemStats<MemStatsDefault>;
195 template class MemStats<MemStatsAdditionalInfo>;
196 } // namespace panda::mem
197