• 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 
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     RecordAllocateObjects(1, size, type_mem);
31 }
32 
33 template <typename T>
RecordAllocateObjects(size_t total_object_num,size_t total_object_size,SpaceType type_mem)34 void MemStats<T>::RecordAllocateObjects(size_t total_object_num, size_t total_object_size, SpaceType type_mem)
35 {
36     ASSERT(IsHeapSpace(type_mem));
37     RecordAllocate(total_object_size, type_mem);
38     if (type_mem == SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT) {
39         // Atomic with acq_rel order reason: data race with humongous_objects_allocated_ with dependecies on reads after
40         // the load and on writes before the store
41         humongous_objects_allocated_.fetch_add(total_object_num, std::memory_order_acq_rel);
42     } else {
43         // Atomic with acq_rel order reason: data race with objects_allocated_ with dependecies on reads after the load
44         // and on writes before the store
45         objects_allocated_.fetch_add(total_object_num, std::memory_order_acq_rel);
46     }
47 }
48 
49 template <typename T>
RecordYoungMovedObjects(size_t young_object_num,size_t size,SpaceType type_mem)50 void MemStats<T>::RecordYoungMovedObjects(size_t young_object_num, size_t size, SpaceType type_mem)
51 {
52     ASSERT(IsHeapSpace(type_mem));
53     RecordMoved(size, type_mem);
54     // We can't move SPACE_TYPE_HUMONGOUS_OBJECT
55     ASSERT(type_mem != SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT);
56     // Atomic with acq_rel order reason: data race with last_young_objects_moved_bytes_ with dependecies on reads after
57     // the load and on writes before the store
58     last_young_objects_moved_bytes_.fetch_add(size, std::memory_order_acq_rel);
59     // Atomic with acq_rel order reason: data race with objects_allocated_ with dependecies on reads after the load and
60     // on writes before the store
61     [[maybe_unused]] uint64_t old_val = objects_allocated_.fetch_sub(young_object_num, std::memory_order_acq_rel);
62     ASSERT(old_val >= young_object_num);
63 }
64 
65 template <typename T>
RecordTenuredMovedObjects(size_t tenured_object_num,size_t size,SpaceType type_mem)66 void MemStats<T>::RecordTenuredMovedObjects(size_t tenured_object_num, size_t size, SpaceType type_mem)
67 {
68     ASSERT(IsHeapSpace(type_mem));
69     RecordMoved(size, type_mem);
70     // We can't move SPACE_TYPE_HUMONGOUS_OBJECT
71     ASSERT(type_mem != SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT);
72     // Atomic with acq_rel order reason: data race with objects_allocated_ with dependecies on reads after the load and
73     // on writes before the store
74     [[maybe_unused]] uint64_t old_val = objects_allocated_.fetch_sub(tenured_object_num, std::memory_order_acq_rel);
75     ASSERT(old_val >= tenured_object_num);
76 }
77 
78 template <typename T>
RecordFreeObject(size_t object_size,SpaceType type_mem)79 void MemStats<T>::RecordFreeObject(size_t object_size, SpaceType type_mem)
80 {
81     RecordFreeObjects(1, object_size, type_mem);
82 }
83 
84 template <typename T>
RecordFreeObjects(size_t total_object_num,size_t total_object_size,SpaceType type_mem)85 void MemStats<T>::RecordFreeObjects(size_t total_object_num, size_t total_object_size, SpaceType type_mem)
86 {
87     ASSERT(IsHeapSpace(type_mem));
88     RecordFree(total_object_size, type_mem);
89     if (type_mem == SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT) {
90         // Atomic with acq_rel order reason: data race with humongous_objects_freed_ with dependecies on reads after the
91         // load and on writes before the store
92         humongous_objects_freed_.fetch_add(total_object_num, std::memory_order_acq_rel);
93     } else {
94         // Atomic with acq_rel order reason: data race with objects_freed_ with dependecies on reads after the load and
95         // on writes before the store
96         objects_freed_.fetch_add(total_object_num, std::memory_order_acq_rel);
97     }
98 }
99 
100 template <typename T>
GetStatistics(HeapManager * heap_manager)101 PandaString MemStats<T>::GetStatistics(HeapManager *heap_manager)
102 {
103     PandaStringStream statistic;
104     statistic << "memory statistics:" << std::endl;
105     statistic << "heap: allocated - " << GetAllocatedHeap() << ", freed - " << GetFreedHeap() << std::endl;
106     statistic << "raw memory: allocated - " << GetAllocated(SpaceType::SPACE_TYPE_INTERNAL) << ", freed - "
107               << GetFreed(SpaceType::SPACE_TYPE_INTERNAL) << std::endl;
108     statistic << "compiler: allocated - " << GetAllocated(SpaceType::SPACE_TYPE_CODE) << std::endl;
109     statistic << "ArenaAllocator: allocated - " << GetAllocated(SpaceType::SPACE_TYPE_COMPILER) << std::endl;
110     statistic << "total footprint now - " << GetTotalFootprint() << std::endl;
111     statistic << "total allocated object - " << GetTotalObjectsAllocated() << std::endl;
112     statistic << "min GC pause time - " << GetMinGCPause() << std::endl;
113     statistic << "max GC pause time - " << GetMaxGCPause() << std::endl;
114     statistic << "average GC pause time - " << GetAverageGCPause() << std::endl;
115     statistic << "total GC pause time - " << GetTotalGCPause() << std::endl;
116     auto additional_statistics = static_cast<T *>(this)->GetAdditionalStatistics(heap_manager);
117     return statistic.str() + additional_statistics;
118 }
119 
120 template <typename T>
GetTotalObjectsAllocated() const121 [[nodiscard]] uint64_t MemStats<T>::GetTotalObjectsAllocated() const
122 {
123     // Atomic with acquire order reason: data race with objects_allocated_ with dependecies on reads after the load
124     // which should become visible
125     return objects_allocated_.load(std::memory_order_acquire);
126 }
127 
128 template <typename T>
GetTotalObjectsFreed() const129 [[nodiscard]] uint64_t MemStats<T>::GetTotalObjectsFreed() const
130 {
131     // Atomic with acquire order reason: data race with objects_freed_ with dependecies on reads after the load which
132     // should become visible
133     return objects_freed_.load(std::memory_order_acquire);
134 }
135 
136 template <typename T>
GetTotalRegularObjectsAllocated() const137 [[nodiscard]] uint64_t MemStats<T>::GetTotalRegularObjectsAllocated() const
138 {
139     return GetTotalObjectsAllocated() - GetTotalHumongousObjectsAllocated();
140 }
141 
142 template <typename T>
GetTotalRegularObjectsFreed() const143 [[nodiscard]] uint64_t MemStats<T>::GetTotalRegularObjectsFreed() const
144 {
145     return GetTotalObjectsFreed() - GetTotalHumongousObjectsFreed();
146 }
147 
148 template <typename T>
GetTotalHumongousObjectsAllocated() const149 [[nodiscard]] uint64_t MemStats<T>::GetTotalHumongousObjectsAllocated() const
150 {
151     // Atomic with acquire order reason: data race with humongous_objects_allocated_ with dependecies on reads after the
152     // load which should become visible
153     return humongous_objects_allocated_.load(std::memory_order_acquire);
154 }
155 
156 template <typename T>
GetTotalHumongousObjectsFreed() const157 [[nodiscard]] uint64_t MemStats<T>::GetTotalHumongousObjectsFreed() const
158 {
159     // Atomic with acquire order reason: data race with humongous_objects_freed_ with dependecies on reads after the
160     // load which should become visible
161     return humongous_objects_freed_.load(std::memory_order_acquire);
162 }
163 
164 template <typename T>
GetObjectsCountAlive() const165 [[nodiscard]] uint64_t MemStats<T>::GetObjectsCountAlive() const
166 {
167     return GetTotalObjectsAllocated() - GetTotalObjectsFreed();
168 }
169 
170 template <typename T>
GetRegularObjectsCountAlive() const171 [[nodiscard]] uint64_t MemStats<T>::GetRegularObjectsCountAlive() const
172 {
173     return GetTotalRegularObjectsAllocated() - GetTotalRegularObjectsFreed();
174 }
175 
176 template <typename T>
GetHumonguousObjectsCountAlive() const177 [[nodiscard]] uint64_t MemStats<T>::GetHumonguousObjectsCountAlive() const
178 {
179     return GetTotalHumongousObjectsAllocated() - GetTotalHumongousObjectsFreed();
180 }
181 
182 template <typename T>
GetLastYoungObjectsMovedBytes() const183 [[nodiscard]] uint64_t MemStats<T>::GetLastYoungObjectsMovedBytes() const
184 {
185     // Atomic with acquire order reason: data race with last_young_objects_moved_bytes_ with dependecies on reads after
186     // the load which should become visible
187     return last_young_objects_moved_bytes_.load(std::memory_order_acquire);
188 }
189 
190 template <typename T>
RecordGCPauseStart()191 void MemStats<T>::RecordGCPauseStart()
192 {
193     pause_start_time_ = clock::now();
194 }
195 
196 template <typename T>
RecordGCPauseEnd()197 void MemStats<T>::RecordGCPauseEnd()
198 {
199     duration pause_time = clock::now() - pause_start_time_;
200     if (pause_count_) {
201         min_pause_ = std::min(min_pause_, pause_time);
202         max_pause_ = std::max(max_pause_, pause_time);
203     } else {
204         min_pause_ = pause_time;
205         max_pause_ = pause_time;
206     }
207     pause_count_++;
208     sum_pause_ += pause_time;
209 }
210 
211 template <typename T>
GetMinGCPause() const212 uint64_t MemStats<T>::GetMinGCPause() const
213 {
214     return std::chrono::duration_cast<std::chrono::milliseconds>(min_pause_).count();
215 }
216 
217 template <typename T>
GetMaxGCPause() const218 uint64_t MemStats<T>::GetMaxGCPause() const
219 {
220     return std::chrono::duration_cast<std::chrono::milliseconds>(max_pause_).count();
221 }
222 
223 template <typename T>
GetAverageGCPause() const224 uint64_t MemStats<T>::GetAverageGCPause() const
225 {
226     return pause_count_ ? std::chrono::duration_cast<std::chrono::milliseconds>(sum_pause_).count() / pause_count_ : 0;
227 }
228 
229 template <typename T>
GetTotalGCPause() const230 uint64_t MemStats<T>::GetTotalGCPause() const
231 {
232     return std::chrono::duration_cast<std::chrono::milliseconds>(sum_pause_).count();
233 }
234 
235 template class MemStats<MemStatsDefault>;
236 template class MemStats<MemStatsAdditionalInfo>;
237 }  // namespace panda::mem
238