1 /*
2 * Copyright (c) 2023 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 ROSEN_MODULES_TEXGINE_SRC_UTILS_MEMORY_REPORTER_H
17 #define ROSEN_MODULES_TEXGINE_SRC_UTILS_MEMORY_REPORTER_H
18
19 #include <cstring>
20 #include <map>
21 #include <memory>
22 #include <set>
23 #include <string>
24 #include <vector>
25
26 #include "texgine/typography.h"
27 #include "texgine/utils/memory_usage_scope.h"
28 #include "variant_font_style_set.h"
29 #include "variant_span.h"
30
31 struct hb_blob_t;
32
33 namespace OHOS {
34 namespace Rosen {
35 namespace TextEngine {
36 #define DECLARE_CLASS_RMU(type) \
37 void type::ReportMemoryUsage(const std::string &member, bool needThis) const
38
39 #define DECLARE_RMU(type) \
40 void ReportMemoryUsage(const std::string &member, type const &that, bool needThis)
41
42 #define MEMORY_USAGE_REPORT(member) \
43 OHOS::Rosen::TextEngine::ReportMemoryUsage(#member, currentVal.member, false)
44
45 #define MEMORY_USAGE_SCOPE(classname, var) \
46 MemoryUsageScope s(std::string(classname) + " " + member); \
47 if (needThis) { DoReportMemoryUsage("*this", sizeof(var)); } \
48 [[maybe_unused]] const auto ¤tVal = var
49
50 template<class T>
GetTypeName()51 std::string GetTypeName()
52 {
53 std::string nameT = __PRETTY_FUNCTION__;
54 nameT = nameT.substr(nameT.find("T = "));
55 nameT = nameT.substr(strlen("T = "), nameT.length() - strlen("T = ") - 1);
56 constexpr const char *str = "std::variant<std::shared_ptr<TextSpan>, std::shared_ptr<AnySpan> >";
57 auto it = nameT.find(str);
58 if (it != std::string::npos) {
59 nameT = nameT.replace(it, strlen(str), "VariantSpan");
60 }
61 return nameT;
62 }
63
64 template<class T>
65 void ReportMemoryUsage(const std::string &member, const T &t, bool needThis = true);
66 template<class T>
67 void ReportMemoryUsage(const std::string &member, const std::vector<T> &vec, bool needThis = true);
68 template<class T>
69 void ReportMemoryUsage(const std::string &member, const std::shared_ptr<T> &sp, bool needThis = true);
70 template<class T>
71 void ReportMemoryUsage(const std::string &member, const std::unique_ptr<T> &up, bool needThis = true);
72 template<class K, class V>
73 void ReportMemoryUsage(const std::string &member, const std::map<K, V> &m, bool needThis = true);
74
75 struct StyledSpan;
76 class CmapParser;
77 class Ranges;
78 class Typeface;
79 class CharGroups;
80 class FontFeatures;
81
82 DECLARE_RMU(std::string);
83 DECLARE_RMU(struct LineMetrics);
84 DECLARE_RMU(struct TypographyStyle);
85 DECLARE_RMU(VariantSpan);
86 DECLARE_RMU(struct StyledSpan);
87 DECLARE_RMU(AnySpan);
88 DECLARE_RMU(FontProviders);
89 DECLARE_RMU(IFontProvider);
90 DECLARE_RMU(TextSpan);
91 DECLARE_RMU(Typeface);
92 DECLARE_RMU(hb_blob_t *);
93 DECLARE_RMU(CharGroups);
94 DECLARE_RMU(struct TextStyle);
95 DECLARE_RMU(CmapParser);
96 DECLARE_RMU(FontFeatures);
97 DECLARE_RMU(Ranges);
98
99 #ifdef TEXGINE_ENABLE_MEMORY
100 #define DEFINE_RMU(type) \
101 template<> \
102 DECLARE_RMU(type) \
103 { \
104 DoReportMemoryUsage(member, sizeof(that)); \
105 }
106
107 DEFINE_RMU(uint16_t);
108 DEFINE_RMU(uint32_t);
109 DEFINE_RMU(int32_t);
110 DEFINE_RMU(double);
111 DEFINE_RMU(VariantFontStyleSet);
112 DEFINE_RMU(struct TextShadow);
113 DEFINE_RMU(struct Glyph);
114 #endif
115
116 template<class T>
ReportMemoryUsage(const std::string & member,const T & t,bool needThis)117 void ReportMemoryUsage(const std::string &member, const T &t, bool needThis)
118 {
119 DoReportMemoryUsage(member, sizeof(t));
120 }
121
122 template<class T>
ReportMemoryUsage(const std::string & member,const std::vector<T> & that,bool needThis)123 void ReportMemoryUsage(const std::string &member, const std::vector<T> &that, bool needThis)
124 {
125 auto nameT = GetTypeName<T>();
126 MEMORY_USAGE_SCOPE("v<" + nameT + ">", that);
127 // 16 is the vector`s base memory footprint
128 int baseMemory = 16;
129 if (that.capacity() != 0) {
130 DoReportMemoryUsage("*external", baseMemory + sizeof(T) * (that.capacity() - that.size()));
131 for (size_t i = 0; i < that.size(); i++) {
132 ReportMemoryUsage(member + "[?]", that[i], true);
133 }
134 }
135 }
136
137 template<class T>
ReportMemoryUsage(const std::string & member,const std::shared_ptr<T> & that,bool needThis)138 void ReportMemoryUsage(const std::string &member, const std::shared_ptr<T> &that, bool needThis)
139 {
140 static std::set<void *> ptrs;
141 if (ptrs.find((void *)(that.get())) != ptrs.end()) {
142 return;
143 }
144 ptrs.insert((void *)(that.get()));
145
146 auto nameT = GetTypeName<T>();
147 if (that != nullptr) {
148 ReportMemoryUsage(member, *that, true);
149 }
150 }
151
152 template<class T>
ReportMemoryUsage(const std::string & member,const std::unique_ptr<T> & that,bool needThis)153 void ReportMemoryUsage(const std::string &member, const std::unique_ptr<T> &that, bool needThis)
154 {
155 static std::set<void *> ptrs;
156 if (ptrs.find((void *)(that.get())) != ptrs.end()) {
157 return;
158 }
159 ptrs.insert((void *)(that.get()));
160
161 auto nameT = GetTypeName<T>();
162 if (that != nullptr) {
163 ReportMemoryUsage(member, *that, true);
164 }
165 }
166
167 template<class K, class V>
ReportMemoryUsage(const std::string & member,const std::map<K,V> & that,bool needThis)168 void ReportMemoryUsage(const std::string &member, const std::map<K, V> &that, bool needThis)
169 {
170 if (that.size()) {
171 auto nameK = GetTypeName<K>();
172 auto nameV = GetTypeName<V>();
173 MEMORY_USAGE_SCOPE("m<" + nameK + ", " + nameV + ">", that);
174 // in std::map, the size of key, if more than 8, it`s base memory footprint is 8 + 40
175 // else base memory footprint is 40
176 unsigned long memoryDelta = 8;
177 unsigned long baseMemory = 40;
178 unsigned long sizeLimit = 8;
179 DoReportMemoryUsage("*external", static_cast<int>(
180 that.size() * ((sizeof(K) < sizeLimit ? 0 : memoryDelta) + baseMemory + sizeof(K) + sizeof(V))));
181 }
182 }
183 } // namespace TextEngine
184 } // namespace Rosen
185 } // namespace OHOS
186
187 #endif // ROSEN_MODULES_TEXGINE_SRC_UTILS_MEMORY_REPORTER_H
188