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 #include "utils/memory_reporter.h"
17
18 #include <cassert>
19 #include <mutex>
20 #include <sstream>
21 #include <stack>
22
23 #include "hb.h"
24 #include "line_metrics.h"
25 #include "texgine/any_span.h"
26 #include "texgine/dynamic_font_provider.h"
27 #include "texgine/theme_font_provider.h"
28 #include "texgine/system_font_provider.h"
29 #include "typeface.h"
30 #include "typography_impl.h"
31
32 namespace OHOS {
33 namespace Rosen {
34 namespace TextEngine {
35 //Enable memory test
36 #ifdef TEXGINE_ENABLE_MEMORY
37 class MemoryReporter {
38 public:
39 static MemoryReporter &GetInstance();
40 void Enter(const std::string &scopeType);
41 void Exit();
42 void Report(const std::string &member, double usage);
43
44 private:
45 MemoryReporter() = default;
46 ~MemoryReporter();
47 MemoryReporter(const MemoryReporter &) = delete;
48 MemoryReporter(MemoryReporter &&) = delete;
49 MemoryReporter& operator=(const MemoryReporter &) = delete;
50 MemoryReporter& operator=(MemoryReporter &&) = delete;
51
52 uint64_t now_ = 0;
53 std::vector<std::pair<uint64_t, std::string>> contents_;
54 std::stack<std::string> scopeStack_ = {};
55 };
56
GetInstance()57 MemoryReporter &MemoryReporter::GetInstance()
58 {
59 static MemoryReporter instance;
60 return instance;
61 }
62
Enter(const std::string & scopeType)63 void MemoryReporter::Enter(const std::string &scopeType)
64 {
65 scopeStack_.push(scopeType);
66 contents_.push_back(std::make_pair(now_, "B" + scopeStack_.top()));
67 }
68
Exit()69 void MemoryReporter::Exit()
70 {
71 scopeStack_.pop();
72 contents_.push_back(std::make_pair(now_, "E"));
73 }
74
Report(const std::string & member,double usage)75 void MemoryReporter::Report(const std::string &member, double usage)
76 {
77 contents_.push_back(std::make_pair(now_, "B" + scopeStack_.top() + "::" + member));
78 now_ += usage;
79 contents_.push_back(std::make_pair(now_, "Cusage|" + std::to_string(now_)));
80 contents_.push_back(std::make_pair(now_, "E"));
81 }
82
~MemoryReporter()83 MemoryReporter::~MemoryReporter()
84 {
85 auto fp = fopen("texgine_usage.trace", "w");
86 if (fp == nullptr) {
87 return;
88 }
89
90 fprintf(fp, "# tracer: nop\n");
91 for (const auto &[timeUs, content] : contents_) {
92 fprintf(fp, "texgine-1 (1) [000] .... %.6lf: tracing_mark_write: %c|1|%s\n",
93 timeUs / 1e6, content[0], content.substr(1).c_str());
94 }
95
96 fclose(fp);
97 }
98
MemoryUsageScope(const std::string & name)99 MemoryUsageScope::MemoryUsageScope(const std::string &name)
100 {
101 MemoryReporter::GetInstance().Enter(name);
102 }
103
~MemoryUsageScope()104 MemoryUsageScope::~MemoryUsageScope()
105 {
106 MemoryReporter::GetInstance().Exit();
107 }
108
DoReportMemoryUsage(const std::string & name,int usage)109 void DoReportMemoryUsage(const std::string &name, int usage)
110 {
111 MemoryReporter::GetInstance().Report(name, usage);
112 }
113 #else
114 MemoryUsageScope::MemoryUsageScope(const std::string &name)
115 {
116 }
117
118 MemoryUsageScope::~MemoryUsageScope()
119 {
120 }
121
122 void DoReportMemoryUsage(const std::string &name, int usage)
123 {
124 }
125 #endif
126
DECLARE_RMU(std::string)127 DECLARE_RMU(std::string)
128 {
129 /*
130 * The capacity of string 16, 24 is the the critical value of string type memory usage
131 * If need calculate this pointer:
132 * If the capacity of string less than 16, it`s memory usage is 32
133 * If the capacity of string more than 16 and less than 24, it`s memory usage is 64
134 * If the capacity of string more than 24, it`s memory is 80 + (capacity - 64) / 16 * 16
135 * If don`t need calculate this pointer:
136 * If the capacity of string >= 16 and < 24, it`s memory usage is 32
137 * else it`s memory usage is 32 + (capacity - 24) / 16 * 16
138 */
139 unsigned long fisrtCapacity = 16;
140 unsigned long secondCapacity = 24;
141 unsigned long baseMemory = 16;
142 unsigned long fisrtMemory = 32;
143 unsigned long secondMemory = 64;
144 unsigned long thirdMemory = 80;
145
146 if (needThis) {
147 if (that.capacity() < fisrtCapacity) {
148 DoReportMemoryUsage(member, fisrtMemory);
149 } else if (that.capacity() < secondCapacity) {
150 DoReportMemoryUsage(member, secondMemory);
151 } else {
152 DoReportMemoryUsage(member, thirdMemory + (that.capacity() - secondCapacity) / fisrtCapacity * baseMemory);
153 }
154 return;
155 }
156
157 if (that.capacity() >= fisrtCapacity && that.capacity() < secondCapacity) {
158 DoReportMemoryUsage(member, fisrtMemory);
159 } else {
160 DoReportMemoryUsage(member, fisrtMemory + (that.capacity() - secondCapacity) / fisrtCapacity * baseMemory);
161 }
162 }
163
DECLARE_RMU(struct LineMetrics)164 DECLARE_RMU(struct LineMetrics)
165 {
166 MEMORY_USAGE_SCOPE("LineMetrics", that);
167 MEMORY_USAGE_REPORT(lineSpans);
168 }
169
DECLARE_RMU(struct TypographyStyle)170 DECLARE_RMU(struct TypographyStyle)
171 {
172 MEMORY_USAGE_SCOPE("Typography::Style", that);
173 MEMORY_USAGE_REPORT(fontFamilies);
174 MEMORY_USAGE_REPORT(ellipsis);
175 MEMORY_USAGE_REPORT(lineStyle.fontFamilies);
176 MEMORY_USAGE_REPORT(locale);
177 }
178
DECLARE_RMU(VariantSpan)179 DECLARE_RMU(VariantSpan)
180 {
181 if (auto ts = that.TryToTextSpan(); ts != nullptr) {
182 ReportMemoryUsage(member, *ts, needThis);
183 }
184
185 if (auto as = that.TryToAnySpan(); as != nullptr) {
186 ReportMemoryUsage(member, *as, needThis);
187 }
188 }
189
DECLARE_RMU(AnySpan)190 DECLARE_RMU(AnySpan)
191 {
192 that.ReportMemoryUsage(member, needThis);
193 }
194
DECLARE_CLASS_RMU(AnySpan)195 DECLARE_CLASS_RMU(AnySpan)
196 {
197 MEMORY_USAGE_SCOPE("AnySpan", *this);
198 }
199
DECLARE_RMU(Typography)200 DECLARE_RMU(Typography)
201 {
202 that.ReportMemoryUsage(member, needThis);
203 }
204
DECLARE_CLASS_RMU(TypographyImpl)205 DECLARE_CLASS_RMU(TypographyImpl)
206 {
207 MEMORY_USAGE_SCOPE("TypographyImpl", *this);
208 MEMORY_USAGE_REPORT(lineMetrics_);
209 MEMORY_USAGE_REPORT(typographyStyle_);
210 MEMORY_USAGE_REPORT(spans_);
211 MEMORY_USAGE_REPORT(fontProviders_);
212 }
213
DECLARE_RMU(FontProviders)214 DECLARE_RMU(FontProviders)
215 {
216 MEMORY_USAGE_SCOPE("FontProviders", that);
217 MEMORY_USAGE_REPORT(providers_);
218 MEMORY_USAGE_REPORT(fontStyleSetCache_);
219 }
220
DECLARE_RMU(IFontProvider)221 DECLARE_RMU(IFontProvider)
222 {
223 that.ReportMemoryUsage(member, needThis);
224 }
225
DECLARE_CLASS_RMU(IFontProvider)226 DECLARE_CLASS_RMU(IFontProvider)
227 {
228 MEMORY_USAGE_SCOPE("IFontProvider", *this);
229 }
230
DECLARE_CLASS_RMU(DynamicFontProvider)231 DECLARE_CLASS_RMU(DynamicFontProvider)
232 {
233 MEMORY_USAGE_SCOPE("DynamicFontProvider", *this);
234 MEMORY_USAGE_REPORT(fontStyleSetMap_);
235 }
236
DECLARE_CLASS_RMU(ThemeFontProvider)237 DECLARE_CLASS_RMU(ThemeFontProvider)
238 {
239 MEMORY_USAGE_SCOPE("ThemeFontProvider", *this);
240 MEMORY_USAGE_REPORT(themeFontStyleSet_);
241 }
242
DECLARE_CLASS_RMU(SystemFontProvider)243 DECLARE_CLASS_RMU(SystemFontProvider)
244 {
245 MEMORY_USAGE_SCOPE("SystemFontProvider", *this);
246 }
247
DECLARE_RMU(TextSpan)248 DECLARE_RMU(TextSpan)
249 {
250 MEMORY_USAGE_SCOPE("TextSpan", that);
251 MEMORY_USAGE_REPORT(typeface_);
252 MEMORY_USAGE_REPORT(u16vect_);
253 MEMORY_USAGE_REPORT(glyphWidths_);
254 MEMORY_USAGE_REPORT(cgs_);
255 }
256
DECLARE_RMU(Typeface)257 DECLARE_RMU(Typeface)
258 {
259 MEMORY_USAGE_SCOPE("Typeface", that);
260 MEMORY_USAGE_REPORT(hblob_);
261 MEMORY_USAGE_REPORT(cmapParser_);
262 }
263
DECLARE_RMU(hb_blob_t *)264 DECLARE_RMU(hb_blob_t *)
265 {
266 if (that == nullptr) {
267 return;
268 }
269 DoReportMemoryUsage(member, hb_blob_get_length(const_cast<hb_blob_t *>(that)));
270 }
271
DECLARE_RMU(CharGroups)272 DECLARE_RMU(CharGroups)
273 {
274 MEMORY_USAGE_SCOPE("CharGroups", that);
275 MEMORY_USAGE_REPORT(pcgs_);
276 }
277
DECLARE_RMU(struct TextStyle)278 DECLARE_RMU(struct TextStyle)
279 {
280 MEMORY_USAGE_SCOPE("TextSpan::Style", that);
281 MEMORY_USAGE_REPORT(fontFamilies);
282 MEMORY_USAGE_REPORT(shadows);
283 MEMORY_USAGE_REPORT(fontFeature);
284 }
285
DECLARE_RMU(CmapParser)286 DECLARE_RMU(CmapParser)
287 {
288 MEMORY_USAGE_SCOPE("CmapParser", that);
289 MEMORY_USAGE_REPORT(ranges_);
290 }
291
DECLARE_RMU(CharGroup)292 DECLARE_RMU(CharGroup)
293 {
294 MEMORY_USAGE_SCOPE("CharGroup", that);
295 MEMORY_USAGE_REPORT(chars);
296 MEMORY_USAGE_REPORT(glyphs);
297 MEMORY_USAGE_REPORT(typeface);
298 }
299
DECLARE_RMU(FontFeatures)300 DECLARE_RMU(FontFeatures)
301 {
302 MEMORY_USAGE_SCOPE("FontFeatures", that);
303 MEMORY_USAGE_REPORT(features_);
304 }
305
DECLARE_RMU(Ranges)306 DECLARE_RMU(Ranges)
307 {
308 MEMORY_USAGE_SCOPE("Ranges", that);
309 MEMORY_USAGE_REPORT(ranges_);
310 MEMORY_USAGE_REPORT(singles_);
311 }
312
313 #ifdef TEXGINE_ENABLE_MEMORY
314 DEFINE_RMU(struct Ranges::Range);
315 #endif
316 } // namespace TextEngine
317 } // namespace Rosen
318 } // namespace OHOS
319