1 /**
2 * Copyright (c) 2021-2024 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 ark::mem {
26
27 template <typename T>
RecordAllocateObject(size_t size,SpaceType typeMem)28 void MemStats<T>::RecordAllocateObject(size_t size, SpaceType typeMem)
29 {
30 RecordAllocateObjects(1, size, typeMem);
31 }
32
33 template <typename T>
RecordAllocateObjects(size_t totalObjectNum,size_t totalObjectSize,SpaceType typeMem)34 void MemStats<T>::RecordAllocateObjects(size_t totalObjectNum, size_t totalObjectSize, SpaceType typeMem)
35 {
36 ASSERT(IsHeapSpace(typeMem));
37 RecordAllocate(totalObjectSize, typeMem);
38 if (typeMem == 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 humongousObjectsAllocated_.fetch_add(totalObjectNum, 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 objectsAllocated_.fetch_add(totalObjectNum, std::memory_order_acq_rel);
46 }
47 }
48
49 template <typename T>
RecordYoungMovedObjects(size_t youngObjectNum,size_t size,SpaceType typeMem)50 void MemStats<T>::RecordYoungMovedObjects(size_t youngObjectNum, size_t size, SpaceType typeMem)
51 {
52 ASSERT(IsHeapSpace(typeMem));
53 RecordMoved(size, typeMem);
54 // We can't move SPACE_TYPE_HUMONGOUS_OBJECT
55 ASSERT(typeMem != 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 lastYoungObjectsMovedBytes_.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 oldVal = objectsAllocated_.fetch_sub(youngObjectNum, std::memory_order_acq_rel);
62 ASSERT(oldVal >= youngObjectNum);
63 }
64
65 template <typename T>
RecordTenuredMovedObjects(size_t tenuredObjectNum,size_t size,SpaceType typeMem)66 void MemStats<T>::RecordTenuredMovedObjects(size_t tenuredObjectNum, size_t size, SpaceType typeMem)
67 {
68 ASSERT(IsHeapSpace(typeMem));
69 RecordMoved(size, typeMem);
70 // We can't move SPACE_TYPE_HUMONGOUS_OBJECT
71 ASSERT(typeMem != 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 oldVal = objectsAllocated_.fetch_sub(tenuredObjectNum, std::memory_order_acq_rel);
75 ASSERT(oldVal >= tenuredObjectNum);
76 }
77
78 template <typename T>
RecordFreeObject(size_t objectSize,SpaceType typeMem)79 void MemStats<T>::RecordFreeObject(size_t objectSize, SpaceType typeMem)
80 {
81 RecordFreeObjects(1, objectSize, typeMem);
82 }
83
84 template <typename T>
RecordFreeObjects(size_t totalObjectNum,size_t totalObjectSize,SpaceType typeMem)85 void MemStats<T>::RecordFreeObjects(size_t totalObjectNum, size_t totalObjectSize, SpaceType typeMem)
86 {
87 ASSERT(IsHeapSpace(typeMem));
88 RecordFree(totalObjectSize, typeMem);
89 if (typeMem == 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 humongousObjectsFreed_.fetch_add(totalObjectNum, 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 objectsFreed_.fetch_add(totalObjectNum, std::memory_order_acq_rel);
97 }
98 }
99
100 template <typename T>
GetStatistics()101 PandaString MemStats<T>::GetStatistics()
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 auto additionalStatistics = static_cast<T *>(this)->GetAdditionalStatistics();
113 return statistic.str() + additionalStatistics;
114 }
115
116 template <typename T>
GetTotalObjectsAllocated() const117 [[nodiscard]] uint64_t MemStats<T>::GetTotalObjectsAllocated() const
118 {
119 // Atomic with acquire order reason: data race with objects_allocated_ with dependecies on reads after the load
120 // which should become visible
121 return objectsAllocated_.load(std::memory_order_acquire);
122 }
123
124 template <typename T>
GetTotalObjectsFreed() const125 [[nodiscard]] uint64_t MemStats<T>::GetTotalObjectsFreed() const
126 {
127 // Atomic with acquire order reason: data race with objects_freed_ with dependecies on reads after the load which
128 // should become visible
129 return objectsFreed_.load(std::memory_order_acquire);
130 }
131
132 template <typename T>
GetTotalRegularObjectsAllocated() const133 [[nodiscard]] uint64_t MemStats<T>::GetTotalRegularObjectsAllocated() const
134 {
135 return GetTotalObjectsAllocated() - GetTotalHumongousObjectsAllocated();
136 }
137
138 template <typename T>
GetTotalRegularObjectsFreed() const139 [[nodiscard]] uint64_t MemStats<T>::GetTotalRegularObjectsFreed() const
140 {
141 return GetTotalObjectsFreed() - GetTotalHumongousObjectsFreed();
142 }
143
144 template <typename T>
GetTotalHumongousObjectsAllocated() const145 [[nodiscard]] uint64_t MemStats<T>::GetTotalHumongousObjectsAllocated() const
146 {
147 // Atomic with acquire order reason: data race with humongous_objects_allocated_ with dependecies on reads after the
148 // load which should become visible
149 return humongousObjectsAllocated_.load(std::memory_order_acquire);
150 }
151
152 template <typename T>
GetTotalHumongousObjectsFreed() const153 [[nodiscard]] uint64_t MemStats<T>::GetTotalHumongousObjectsFreed() const
154 {
155 // Atomic with acquire order reason: data race with humongous_objects_freed_ with dependecies on reads after the
156 // load which should become visible
157 return humongousObjectsFreed_.load(std::memory_order_acquire);
158 }
159
160 template <typename T>
GetObjectsCountAlive() const161 [[nodiscard]] uint64_t MemStats<T>::GetObjectsCountAlive() const
162 {
163 return GetTotalObjectsAllocated() - GetTotalObjectsFreed();
164 }
165
166 template <typename T>
GetRegularObjectsCountAlive() const167 [[nodiscard]] uint64_t MemStats<T>::GetRegularObjectsCountAlive() const
168 {
169 return GetTotalRegularObjectsAllocated() - GetTotalRegularObjectsFreed();
170 }
171
172 template <typename T>
GetHumonguousObjectsCountAlive() const173 [[nodiscard]] uint64_t MemStats<T>::GetHumonguousObjectsCountAlive() const
174 {
175 return GetTotalHumongousObjectsAllocated() - GetTotalHumongousObjectsFreed();
176 }
177
178 template <typename T>
GetLastYoungObjectsMovedBytes() const179 [[nodiscard]] uint64_t MemStats<T>::GetLastYoungObjectsMovedBytes() const
180 {
181 // Atomic with acquire order reason: data race with last_young_objects_moved_bytes_ with dependecies on reads after
182 // the load which should become visible
183 return lastYoungObjectsMovedBytes_.load(std::memory_order_acquire);
184 }
185
186 template class MemStats<MemStatsDefault>;
187 template class MemStats<MemStatsAdditionalInfo>;
188 } // namespace ark::mem
189