• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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