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