• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "htrace_mem_parser.h"
16 #include "clock_filter_ex.h"
17 #include "htrace_event_parser.h"
18 #include "measure_filter.h"
19 #include "memory_plugin_common.pbreader.h"
20 #include "memory_plugin_config.pbreader.h"
21 #include "memory_plugin_result.pbreader.h"
22 #include "process_filter.h"
23 #include "stat_filter.h"
24 #include "system_event_measure_filter.h"
25 
26 namespace SysTuning {
27 namespace TraceStreamer {
28 std::vector<std::string> g_unknownAnonMemInfo = {
29     "[anon]",
30     "[anon:libwebview reservation]",
31     "[anon:atexit handlers]",
32     "[anon:cfi shadow]",
33     "[anon:thread signal stack]",
34     "[anon:bionic_alloc_small_objects]",
35     "[anon:bionic_alloc_lob]",
36     "[anon:linker_alloc]",
37     "[anon:System property context nodes]",
38     "[anon:arc4random data]",
39 };
40 std::map<std::string, uint32_t> g_checkMemStart = {
41     {"[stack", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_STACK},
42     {"[anon:stack_and_tls:", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_STACK},
43     {"[anon:stack:", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_STACK},
44     {"[anon:signal_stack:", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_STACK},
45     {"[anon:maple_alloc_ros]", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JS_HEAP},
46     {"[anon:dalvik-allocspace", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JS_HEAP},
47     {"[anon:dalvik-main space", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JS_HEAP},
48     {"[anon:dalvik-large object", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JS_HEAP},
49     {"[anon:dalvik-free list large", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JS_HEAP},
50     {"[anon:dalvik-non moving", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JS_HEAP},
51     {"[anon:dalvik-zygote space", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JS_HEAP},
52     {"[anon:dalvik-", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JAVA_VM},
53     {"/dev/ashmem/jit-zygote-cache", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JAVA_VM},
54     {"/memfd:jit-cache", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JAVA_VM},
55     {"/memfd:jit-zygote-cache", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JAVA_VM},
56     {"[heap]", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_NATIVE_HEAP},
57     {"[anon:libc_malloc", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_NATIVE_HEAP},
58     {"[anon:scudo", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_NATIVE_HEAP},
59     {"[anon:GWP-Asan", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_NATIVE_HEAP},
60 };
61 std::map<std::string, uint32_t> g_checkMemEnd = {
62     {".art", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JS_HEAP},
63     {".art]", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JS_HEAP},
64     {".tty", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_FONT},
65 };
66 std::map<std::string, uint32_t> g_checkMemContain = {
67     {"[anon:ArkJS Heap]", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_JS_HEAP},
68     {"[anon:native_heap:jemalloc]", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_NATIVE_HEAP},
69     {"[heap]", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_NATIVE_HEAP},
70     {"[anon:native_heap:musl]", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_NATIVE_HEAP},
71     {"/dev/ashmem/", (uint32_t)HtraceMemParser::SmapsMemType::SMAPS_MEM_TYPE_ASHMEM},
72 };
HtraceMemParser(TraceDataCache * dataCache,const TraceStreamerFilters * ctx)73 HtraceMemParser::HtraceMemParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx)
74     : EventParserBase(dataCache, ctx)
75 {
76     for (auto i = 0; i < MEM_MAX; i++) {
77         memNameDictMap_.insert(
78             std::make_pair(static_cast<MemInfoType>(i),
79                            traceDataCache_->GetDataIndex(config_.memNameMap_.at(static_cast<MemInfoType>(i)))));
80     }
81     for (auto i = 0; i < ProtoReader::PMEM_PINED_PURG + 1; i++) {
82         sysMemNameDictMap_.insert(std::make_pair(i, traceDataCache_->GetDataIndex(config_.sysMemNameMap_.at(i))));
83     }
84     for (auto i = 0; i < ProtoReader::VMEMINFO_WORKINGSET_RESTORE + 1; i++) {
85         sysVMemNameDictMap_.insert(
86             std::make_pair(i, traceDataCache_->GetDataIndex(config_.sysVirtualMemNameMap_.at(i))));
87     }
88 }
89 
~HtraceMemParser()90 HtraceMemParser::~HtraceMemParser()
91 {
92     TS_LOGI("mem ts MIN:%llu, MAX:%llu", static_cast<unsigned long long>(GetPluginStartTime()),
93             static_cast<unsigned long long>(GetPluginEndTime()));
94 }
Parse(HtraceDataSegment & seg,uint64_t timeStamp,BuiltinClocks clock)95 void HtraceMemParser::Parse(HtraceDataSegment& seg, uint64_t timeStamp, BuiltinClocks clock)
96 {
97     ProtoReader::MemoryData_Reader memData(seg.protoData.data_, seg.protoData.size_);
98     auto newTimeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(clock, timeStamp);
99     UpdatePluginTimeRange(clock, timeStamp, newTimeStamp);
100     zram_ = memData.zram();
101     gpuLimit_ = memData.has_gpu_limit_size() ? memData.gpu_limit_size() : 0;
102     gpuUsed_ = memData.has_gpu_used_size() ? memData.gpu_used_size() : 0;
103     if (memData.has_processesinfo()) {
104         ParseProcessInfo(&memData, newTimeStamp);
105     }
106     if (memData.has_meminfo()) {
107         ParseMemInfo(&memData, newTimeStamp);
108     }
109     if (memData.has_vmeminfo()) {
110         ParseVMemInfo(&memData, newTimeStamp);
111     }
112     if (memData.has_ashmeminfo()) {
113         ParseAshmemInfo(&memData, newTimeStamp);
114     }
115     if (memData.has_dmainfo()) {
116         ParseDmaMemInfo(&memData, newTimeStamp);
117     }
118     if (memData.has_gpumemoryinfo()) {
119         ParseGpuProcessMemInfo(&memData, newTimeStamp);
120     }
121     if (memData.has_gpudumpinfo()) {
122         ParseGpuWindowMemInfo(&memData, newTimeStamp);
123     }
124     if (memData.has_windowinfo()) {
125         ParseWindowManagerServiceInfo(&memData, newTimeStamp);
126     }
127     if (memData.has_cpudumpinfo()) {
128         ParseCpuDumpInfo(&memData, newTimeStamp);
129     }
130     if (memData.has_profilememinfo()) {
131         ParseProfileMemInfo(&memData, newTimeStamp);
132     }
133     if (memData.has_rsdumpinfo()) {
134         ParseRSImageDumpInfo(&memData, newTimeStamp);
135     }
136 }
137 
SpecialDataAddition(ProtoReader::ProcessMemoryInfo_Reader & processMemoryInfo,uint64_t timeStamp,uint32_t ipid,uint32_t hasValue) const138 void HtraceMemParser::SpecialDataAddition(ProtoReader::ProcessMemoryInfo_Reader& processMemoryInfo,
139                                           uint64_t timeStamp,
140                                           uint32_t ipid,
141                                           uint32_t hasValue) const
142 {
143     // processMemoryInfo Special data addition
144     if (processMemoryInfo.has_purg_sum_kb()) {
145         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
146             ipid, memNameDictMap_.at(MEM_PURG_SUM), timeStamp, processMemoryInfo.purg_sum_kb());
147     }
148     if (processMemoryInfo.has_purg_pin_kb()) {
149         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
150             ipid, memNameDictMap_.at(MEM_PURG_PIN), timeStamp, processMemoryInfo.purg_pin_kb());
151     }
152     if (processMemoryInfo.has_gl_pss_kb()) {
153         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
154             ipid, memNameDictMap_.at(MEM_GL_PSS), timeStamp, processMemoryInfo.gl_pss_kb());
155     }
156     if (processMemoryInfo.has_graph_pss_kb()) {
157         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
158             ipid, memNameDictMap_.at(MEM_GRAPH_PSS), timeStamp, processMemoryInfo.graph_pss_kb());
159     }
160     if (hasValue) {
161         streamFilters_->processFilter_->AddProcessMemory(ipid);
162     }
163     if (processMemoryInfo.has_smapinfo()) {
164         ParseSmapsInfoEasy(&processMemoryInfo, timeStamp, ipid);
165     }
166 }
167 
ParseProcessInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const168 void HtraceMemParser::ParseProcessInfo(const ProtoReader::MemoryData_Reader* tracePacket, uint64_t timeStamp) const
169 {
170     if (tracePacket->has_processesinfo()) {
171         streamFilters_->statFilter_->IncreaseStat(TRACE_MEMORY, STAT_EVENT_RECEIVED);
172     }
173     for (auto i = tracePacket->processesinfo(); i; ++i) {
174         ProtoReader::ProcessMemoryInfo_Reader processMemoryInfo(i->ToBytes().data_, i->ToBytes().size_);
175         auto ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(
176             processMemoryInfo.pid(), processMemoryInfo.name().ToStdString());
177         uint32_t hasValue = 0;
178         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
179             ipid, memNameDictMap_.at(MEM_VM_SIZE), timeStamp, processMemoryInfo.vm_size_kb());
180         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
181             ipid, memNameDictMap_.at(MEM_VM_RSS), timeStamp, processMemoryInfo.vm_rss_kb());
182         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
183             ipid, memNameDictMap_.at(MEM_VM_ANON), timeStamp, processMemoryInfo.rss_anon_kb());
184         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
185             ipid, memNameDictMap_.at(MEM_RSS_FILE), timeStamp, processMemoryInfo.rss_file_kb());
186         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
187             ipid, memNameDictMap_.at(MEM_RSS_SHMEM), timeStamp, processMemoryInfo.rss_shmem_kb());
188         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
189             ipid, memNameDictMap_.at(MEM_VM_SWAP), timeStamp, processMemoryInfo.vm_swap_kb());
190         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
191             ipid, memNameDictMap_.at(MEM_VM_LOCKED), timeStamp, processMemoryInfo.vm_locked_kb());
192         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
193             ipid, memNameDictMap_.at(MEM_VM_HWM), timeStamp, processMemoryInfo.vm_hwm_kb());
194         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
195             ipid, memNameDictMap_.at(MEM_OOM_SCORE_ADJ), timeStamp, processMemoryInfo.oom_score_adj());
196 
197         SpecialDataAddition(processMemoryInfo, timeStamp, ipid, hasValue);
198     }
199 }
ParseSmapsPathTypeByPrefix(bool hasX,const std::string & path,const bool hasAppName) const200 uint32_t HtraceMemParser::ParseSmapsPathTypeByPrefix(bool hasX, const std::string& path, const bool hasAppName) const
201 {
202     if (EndWith(path, ".so")) {
203         if (hasX) {
204             if (StartWith(path, "/data/app/") || hasAppName) {
205                 return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_CODE_APP);
206             } else {
207                 return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_CODE_SYS);
208             }
209         } else {
210             if (StartWith(path, "[anon:.bss]/data/app/") || StartWith(path, "/data/app/") || hasAppName) {
211                 return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_APP);
212             } else {
213                 return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_SYS);
214             }
215         }
216     }
217     return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_INVALID);
218 }
ParseSmapsPathTypeBySuffix(bool hasX,const std::string & path,const bool hasAppName) const219 uint32_t HtraceMemParser::ParseSmapsPathTypeBySuffix(bool hasX, const std::string& path, const bool hasAppName) const
220 {
221     if ((EndWith(path, ".jar")) || (EndWith(path, ".apk")) || (EndWith(path, ".vdex")) || (EndWith(path, ".odex")) ||
222         (EndWith(path, ".oat")) || (path.find("dex") != std::string::npos)) {
223         return hasX ? (hasAppName ? static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_CODE_APP)
224                                   : static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_CODE_SYS))
225                     : (hasAppName ? static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_APP)
226                                   : static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_SYS));
227     }
228     return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_INVALID);
229 }
230 
ParseSmapsBlockDetail(ProtoReader::SmapsInfo_Reader & smapsInfo,const std::string & path,const bool hasAppName) const231 uint32_t HtraceMemParser::ParseSmapsBlockDetail(ProtoReader::SmapsInfo_Reader& smapsInfo,
232                                                 const std::string& path,
233                                                 const bool hasAppName) const
234 {
235     bool hasX = smapsInfo.permission().ToStdString().find("x") != std::string::npos;
236     auto type = ParseSmapsPathTypeByPrefix(hasX, path, hasAppName);
237     if (type != static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_INVALID)) {
238         return type;
239     }
240     type = ParseSmapsPathTypeBySuffix(hasX, path, hasAppName);
241     if (type != static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_INVALID)) {
242         return type;
243     }
244     if (hasX && path.find("/bin/") != std::string::npos) {
245         return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_CODE_SYS);
246     }
247     if ((!hasX) && (path.find("/bin/") != std::string::npos || path.find("[anon:.bss]") != std::string::npos)) {
248         return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_SYS);
249     }
250     if (path.find("[bss]") != std::string::npos) {
251         return hasAppName ? static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_APP)
252                           : static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_SYS);
253     }
254     if ((path.find("[anon]") != std::string::npos) || (path.find("[anon:") != std::string::npos)) {
255         if (std::find(g_unknownAnonMemInfo.begin(), g_unknownAnonMemInfo.end(), path) != g_unknownAnonMemInfo.end()) {
256             return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_UNKNOWN_ANON);
257         }
258         return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_NATIVE_HEAP);
259     }
260     return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_INVALID);
261 }
262 
ParseSmapsBlockType(ProtoReader::SmapsInfo_Reader & smapsInfo) const263 uint32_t HtraceMemParser::ParseSmapsBlockType(ProtoReader::SmapsInfo_Reader& smapsInfo) const
264 {
265     std::string path(smapsInfo.path().ToStdString());
266     path.erase(0, path.find_first_not_of(" "));
267     path.erase(path.find_last_not_of(" ") + 1);
268     if (path.empty()) {
269         path = "[anon]";
270     }
271     for (const auto& iter : g_checkMemStart) {
272         if (StartWith(path, iter.first)) {
273             return iter.second;
274         }
275     }
276     for (const auto& iter : g_checkMemEnd) {
277         if (EndWith(path, iter.first)) {
278             return iter.second;
279         }
280     }
281     for (const auto& iter : g_checkMemContain) {
282         if (path.find(iter.first) != std::string::npos) {
283             return iter.second;
284         }
285     }
286     bool hasAppName = path.find("com.huawei.wx") != std::string::npos;
287     uint32_t detailRet = (smapsInfo, path, hasAppName);
288     if (detailRet != static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_INVALID)) {
289         return detailRet;
290     }
291     return hasAppName ? static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_OTHER_APP)
292                       : static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_OTHER_SYS);
293 }
294 
ParseSmapsInfoEasy(const ProtoReader::ProcessMemoryInfo_Reader * memInfo,uint64_t timeStamp,uint64_t ipid) const295 void HtraceMemParser::ParseSmapsInfoEasy(const ProtoReader::ProcessMemoryInfo_Reader* memInfo,
296                                          uint64_t timeStamp,
297                                          uint64_t ipid) const
298 {
299     streamFilters_->statFilter_->IncreaseStat(TRACE_SMAPS, STAT_EVENT_RECEIVED);
300     for (auto i = memInfo->smapinfo(); i; ++i) {
301         ProtoReader::SmapsInfo_Reader smapsInfo(i->ToBytes().data_, i->ToBytes().size_);
302         auto startAddr = "0x" + smapsInfo.start_addr().ToStdString();
303         auto endAddr = "0x" + smapsInfo.end_addr().ToStdString();
304         uint64_t dirty = smapsInfo.dirty();
305         uint64_t swapper = smapsInfo.swapper();
306         uint64_t rss = smapsInfo.rss();
307         uint64_t pss = smapsInfo.pss();
308         uint64_t size = smapsInfo.size();
309         double reside = smapsInfo.reside();
310         DataIndex protection = traceDataCache_->GetDataIndex(smapsInfo.permission().ToStdString());
311         DataIndex path = traceDataCache_->GetDataIndex(smapsInfo.path().ToStdString());
312         uint64_t privateClean = smapsInfo.has_private_clean() ? smapsInfo.private_clean() : 0;
313         uint64_t privateDirty = smapsInfo.has_private_dirty() ? smapsInfo.private_dirty() : 0;
314         uint64_t sharedClean = smapsInfo.has_shared_clean() ? smapsInfo.shared_clean() : 0;
315         uint64_t sharedDirty = smapsInfo.has_shared_dirty() ? smapsInfo.shared_dirty() : 0;
316         uint64_t swap = smapsInfo.has_swap() ? smapsInfo.swap() : 0;
317         uint64_t swapPss = smapsInfo.has_swap_pss() ? smapsInfo.swap_pss() : 0;
318         uint32 type = ParseSmapsBlockType(smapsInfo);
319         traceDataCache_->GetSmapsData()->AppendNewData(timeStamp, ipid, startAddr, endAddr, dirty, swapper, rss, pss,
320                                                        size, reside, protection, path, sharedClean, sharedDirty,
321                                                        privateClean, privateDirty, swap, swapPss, type);
322     }
323 }
324 
ParseMemInfoEasy(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const325 void HtraceMemParser::ParseMemInfoEasy(const ProtoReader::MemoryData_Reader* tracePacket, uint64_t timeStamp) const
326 {
327     if (tracePacket->has_meminfo()) {
328         streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_MEMORY, STAT_EVENT_RECEIVED);
329     }
330     for (auto i = tracePacket->meminfo(); i; ++i) {
331         ProtoReader::SysMeminfo_Reader sysMeminfo(i->ToBytes());
332         if (config_.sysMemNameMap_.find(sysMeminfo.key()) != config_.sysMemNameMap_.end()) {
333             streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData(sysMemNameDictMap_.at(sysMeminfo.key()),
334                                                                              timeStamp, sysMeminfo.value());
335         } else {
336             streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_MEMORY, STAT_EVENT_DATA_INVALID);
337         }
338     }
339 }
340 
ParseVMemInfoEasy(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const341 void HtraceMemParser::ParseVMemInfoEasy(const ProtoReader::MemoryData_Reader* tracePacket, uint64_t timeStamp) const
342 {
343     traceDataCache_->UpdateTraceTime(timeStamp);
344     if (tracePacket->has_vmeminfo()) {
345         streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_RECEIVED);
346     }
347     for (auto i = tracePacket->vmeminfo(); i; ++i) {
348         ProtoReader::SysVMeminfo_Reader sysVMeminfo(i->ToBytes());
349         if (config_.sysVirtualMemNameMap_.find(sysVMeminfo.key()) != config_.sysVirtualMemNameMap_.end()) {
350             streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData(sysVMemNameDictMap_.at(sysVMeminfo.key()),
351                                                                              timeStamp, sysVMeminfo.value());
352         } else {
353             streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_DATA_INVALID);
354         }
355     }
356 }
357 
ParseMemInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const358 void HtraceMemParser::ParseMemInfo(const ProtoReader::MemoryData_Reader* tracePacket, uint64_t timeStamp) const
359 {
360     streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_MEMORY, STAT_EVENT_RECEIVED);
361     for (auto i = tracePacket->meminfo(); i; ++i) {
362         ProtoReader::SysMeminfo_Reader sysMeminfo(i->ToBytes());
363         if (sysMeminfo.key() >= ProtoReader::PMEM_UNSPECIFIED && sysMeminfo.key() <= ProtoReader::PMEM_PINED_PURG) {
364             streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData(sysMemNameDictMap_.at(sysMeminfo.key()),
365                                                                             timeStamp, sysMeminfo.value());
366         } else {
367             streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_MEMORY, STAT_EVENT_DATA_INVALID);
368         }
369     }
370     streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData(zramIndex_, timeStamp, zram_);
371     streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData(gpuLimitSizeIndex_, timeStamp, gpuLimit_);
372     streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData(gpuUsedSizeIndex_, timeStamp, gpuUsed_);
373 }
374 
ParseVMemInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const375 void HtraceMemParser::ParseVMemInfo(const ProtoReader::MemoryData_Reader* tracePacket, uint64_t timeStamp) const
376 {
377     streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_RECEIVED);
378     for (auto i = tracePacket->vmeminfo(); i; ++i) {
379         ProtoReader::SysVMeminfo_Reader sysVMeminfo(i->ToBytes());
380         if (sysVMeminfo.key() >= ProtoReader::VMEMINFO_UNSPECIFIED &&
381             sysVMeminfo.key() <= ProtoReader::VMEMINFO_WORKINGSET_RESTORE) {
382             streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData(sysVMemNameDictMap_.at(sysVMeminfo.key()),
383                                                                              timeStamp, sysVMeminfo.value());
384         } else {
385             // case SysVMeminfoType_INT_MAX_SENTINEL_DO_NOT_USE_:
386             streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_DATA_INVALID);
387         }
388     }
389 }
ParseAshmemInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const390 void HtraceMemParser::ParseAshmemInfo(const ProtoReader::MemoryData_Reader* tracePacket, uint64_t timeStamp) const
391 {
392     if (tracePacket->has_ashmeminfo()) {
393         streamFilters_->statFilter_->IncreaseStat(TRACE_ASHMEM, STAT_EVENT_RECEIVED);
394     }
395     for (auto i = tracePacket->ashmeminfo(); i; ++i) {
396         ProtoReader::AshmemInfo_Reader AshmemInfo(i->ToBytes().data_, i->ToBytes().size_);
397         auto ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(AshmemInfo.pid(),
398                                                                                   AshmemInfo.name().ToStdString());
399         uint32_t adj = AshmemInfo.adj();
400         uint32_t fd = AshmemInfo.fd();
401         DataIndex ashmemNameId = traceDataCache_->GetDataIndex(AshmemInfo.ashmem_name().ToStdString());
402         uint64_t size = AshmemInfo.size();
403         uint32_t ashmemId = AshmemInfo.id();
404         uint64_t time = AshmemInfo.time();
405         uint64_t refCount = AshmemInfo.ref_count();
406         uint64_t purged = AshmemInfo.purged();
407         uint32_t flag = 0;
408         uint64_t pss = 0;
409         auto smapsData = traceDataCache_->GetConstSmapsData();
410         auto smapsCount = smapsData.Size();
411         for (auto j = 0; j < smapsCount; j++) {
412             auto path = traceDataCache_->GetDataFromDict(smapsData.PathIds()[j]);
413             if ((smapsData.Ipids()[j] == ipid) && (path.find("/dev/ashmem/") != std::string::npos)) {
414                 pss += smapsData.Pss()[j] + smapsData.SwapPss()[j];
415             }
416         }
417         traceDataCache_->GetAshMemData()->AppendNewData(ipid, timeStamp, adj, fd, ashmemNameId, size, pss, ashmemId,
418                                                         time, refCount, purged, flag);
419     }
420     AshMemDeduplicate();
421 }
AshMemDeduplicate() const422 void HtraceMemParser::AshMemDeduplicate() const
423 {
424     auto ashMemData = traceDataCache_->GetAshMemData();
425     auto ashMemCount = ashMemData->Size();
426     if (ashMemCount <= 1) {
427         return;
428     }
429 
430     std::vector<std::pair<size_t, size_t>> dataByTs;
431     size_t start = 0;
432     auto ts = ashMemData->TimeStampData()[0];
433     for (auto i = 0; i < ashMemCount; ++i) {
434         auto tsTmp = ashMemData->TimeStampData()[i];
435         if (tsTmp != ts) {
436             dataByTs.emplace_back(std::make_pair(start, i - 1));
437             start = i;
438             ts = tsTmp;
439         }
440     }
441     dataByTs.emplace_back(std::make_pair(start, ashMemCount - 1));
442 
443     for (const auto& iterator : dataByTs) {
444         /* L1 map (key = id+time, value = L2 map)
445            L2 map (key = ipid, value = index) */
446         std::map<std::pair<uint32_t, uint64_t>, std::map<uint64_t, uint64_t>> AshMemMap;
447         for (auto i = iterator.first; i <= iterator.second; ++i) {
448             auto ashmemId = ashMemData->AshmemIds()[i];
449             auto time = ashMemData->Times()[i];
450             auto key = std::make_pair(ashmemId, time);
451             auto ipid = ashMemData->Ipids()[i];
452             auto& pidMap = AshMemMap[key];
453             if (pidMap.find(ipid) == pidMap.end()) {
454                 pidMap.emplace(ipid, i);
455             } else {
456                 ashMemData->SetFlag(i, (uint32_t)MemDeduplicateFlag::MEM_DEDUPLICATE_FLAG_DUP_SAME_PROCESS);
457             }
458         }
459 
460         for (const auto& item : AshMemMap) {
461             auto& pidMap = item.second;
462             auto iter = pidMap.begin();
463             if (iter == pidMap.end()) {
464                 continue;
465             }
466             for (++iter; iter != pidMap.end(); ++iter) {
467                 ashMemData->SetFlag(iter->second, (uint32_t)MemDeduplicateFlag::MEM_DEDUPLICATE_FLAG_DUP_DIFF_PROCESS);
468             }
469         }
470     }
471 }
GetMemProcessType(uint64_t ipid) const472 HtraceMemParser::MemProcessType HtraceMemParser::GetMemProcessType(uint64_t ipid) const
473 {
474     const auto& iterProcess = traceDataCache_->GetConstProcessData(ipid);
475     if (iterProcess.cmdLine_ == "composer_host") {
476         return MemProcessType::PID_TYPE_COMPOSER;
477     } else if (iterProcess.cmdLine_ == "render_service") {
478         return MemProcessType::PID_TYPE_RENDER_SERVICES;
479     } else {
480         return MemProcessType::PID_TYPE_APP;
481     }
482 }
483 
ParseDmaMemInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const484 void HtraceMemParser::ParseDmaMemInfo(const ProtoReader::MemoryData_Reader* tracePacket, uint64_t timeStamp) const
485 {
486     if (tracePacket->has_dmainfo()) {
487         streamFilters_->statFilter_->IncreaseStat(TRACE_DMAMEM, STAT_EVENT_RECEIVED);
488     }
489     for (auto i = tracePacket->dmainfo(); i; ++i) {
490         ProtoReader::DmaInfo_Reader DmaMemInfo(i->ToBytes().data_, i->ToBytes().size_);
491         auto ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(DmaMemInfo.pid(),
492                                                                                   DmaMemInfo.name().ToStdString());
493         uint32_t fd = DmaMemInfo.fd();
494         uint64_t size = DmaMemInfo.size();
495         uint32_t ino = DmaMemInfo.ino();
496         uint64_t expPid = DmaMemInfo.exp_pid();
497         DataIndex expTaskCommId = traceDataCache_->GetDataIndex(DmaMemInfo.exp_task_comm().ToStdString());
498         DataIndex bufNameId = traceDataCache_->GetDataIndex(DmaMemInfo.buf_name().ToStdString());
499         DataIndex expNameId = traceDataCache_->GetDataIndex(DmaMemInfo.exp_name().ToStdString());
500         uint32_t flag = 0;
501         traceDataCache_->GetDmaMemData()->AppendNewData(ipid, timeStamp, fd, size, ino, expPid, expTaskCommId,
502                                                         bufNameId, expNameId, flag);
503     }
504     DmaMemDeduplicate();
505 }
DmaMemDeduplicate() const506 void HtraceMemParser::DmaMemDeduplicate() const
507 {
508     auto dmaMemData = traceDataCache_->GetDmaMemData();
509     auto dmaCount = dmaMemData->Size();
510     if (dmaCount <= 1) {
511         return;
512     }
513 
514     std::vector<std::pair<size_t, size_t>> dataByTs;
515     size_t start = 0;
516     auto ts = dmaMemData->TimeStampData()[0];
517     for (auto i = 0; i < dmaCount; ++i) {
518         auto tsTmp = dmaMemData->TimeStampData()[i];
519         if (tsTmp != ts) {
520             dataByTs.emplace_back(std::make_pair(start, i - 1));
521             start = i;
522             ts = tsTmp;
523         }
524     }
525     dataByTs.emplace_back(std::make_pair(start, dmaCount - 1));
526 
527     for (const auto& iterator : dataByTs) {
528         /* L1 map (key = ino, value = L2 map)
529            L2 map (key = ipid, value = pair(index, MemProcessType)) */
530         std::map<uint32_t, std::map<uint64_t, std::pair<uint64_t, MemProcessType>>> inoMap;
531         std::map<uint32_t /*ino*/, MemProcessType> processTypeMap;
532         for (auto i = iterator.first; i <= iterator.second; ++i) {
533             auto ino = dmaMemData->Inos()[i];
534             auto ipid = dmaMemData->Ipids()[i];
535             auto& pidMap = inoMap[ino];
536             if (pidMap.find(ipid) != pidMap.end()) {
537                 dmaMemData->SetFlag(i, (uint32_t)MemDeduplicateFlag::MEM_DEDUPLICATE_FLAG_DUP_SAME_PROCESS);
538             } else {
539                 auto processType = GetMemProcessType(ipid);
540                 pidMap.emplace(ipid, std::make_pair(i, processType));
541                 if (processTypeMap[ino] < processType) {
542                     processTypeMap[ino] = processType;
543                 }
544             }
545         }
546 
547         for (const auto& item : inoMap) {
548             auto maxPidType = processTypeMap[item.first];
549             const auto& pidMap = item.second;
550             for (const auto& pidItem : pidMap) {
551                 if (pidItem.second.second < maxPidType) {
552                     dmaMemData->SetFlag(pidItem.second.first,
553                                         (uint32_t)MemDeduplicateFlag::MEM_DEDUPLICATE_FLAG_DUP_DIFF_PROCESS);
554                 }
555             }
556         }
557     }
558 }
559 
ParseGpuProcessMemInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const560 void HtraceMemParser::ParseGpuProcessMemInfo(const ProtoReader::MemoryData_Reader* tracePacket,
561                                              uint64_t timeStamp) const
562 {
563     if (tracePacket->has_gpumemoryinfo()) {
564         streamFilters_->statFilter_->IncreaseStat(TRACE_GPU_PROCESS_MEM, STAT_EVENT_RECEIVED);
565     }
566     for (auto i = tracePacket->gpumemoryinfo(); i; ++i) {
567         ProtoReader::GpuMemoryInfo_Reader GpuMemoryInfo(i->ToBytes().data_, i->ToBytes().size_);
568         DataIndex gpuNameId = traceDataCache_->GetDataIndex(GpuMemoryInfo.gpu_name().ToStdString());
569         uint64_t allGpuSize = GpuMemoryInfo.all_gpu_size();
570         if (GpuMemoryInfo.has_gpu_process_info()) {
571             for (auto j = GpuMemoryInfo.gpu_process_info(); j; ++j) {
572                 ProtoReader::GpuProcessInfo_Reader GpuProcessInfo(j->ToBytes().data_, j->ToBytes().size_);
573                 std::string addr = GpuProcessInfo.addr().ToStdString();
574                 uint32_t pid = GpuProcessInfo.pid();
575                 uint32_t tid = GpuProcessInfo.tid();
576                 auto itid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(tid, pid);
577                 auto ipid = streamFilters_->processFilter_->GetOrCreateInternalPid(timeStamp, pid);
578                 uint64_t usedGpuSize = GpuProcessInfo.used_gpu_size();
579 
580                 traceDataCache_->GetGpuProcessMemData()->AppendNewData(timeStamp, gpuNameId, allGpuSize, addr, ipid,
581                                                                        itid, usedGpuSize);
582             }
583         }
584     }
585 }
FillGpuWindowMemInfo(const ProtoReader::GpuDumpInfo_Reader & gpuDumpInfo,uint64_t timeStamp) const586 void HtraceMemParser::FillGpuWindowMemInfo(const ProtoReader::GpuDumpInfo_Reader& gpuDumpInfo, uint64_t timeStamp) const
587 {
588     DataIndex windowNameId = traceDataCache_->GetDataIndex(gpuDumpInfo.window_name().ToStdString());
589     uint64_t windowId = gpuDumpInfo.id();
590     uint64_t purgeableSize = gpuDumpInfo.gpu_purgeable_size();
591     for (auto i = gpuDumpInfo.gpu_detail_info(); i; ++i) {
592         ProtoReader::GpuDetailInfo_Reader GpuDetailInfo(i->ToBytes().data_, i->ToBytes().size_);
593         DataIndex moduleNameId = traceDataCache_->GetDataIndex(GpuDetailInfo.module_name().ToStdString());
594         if (!GpuDetailInfo.has_gpu_sub_info()) {
595             continue;
596         }
597         for (auto j = GpuDetailInfo.gpu_sub_info(); j; ++j) {
598             ProtoReader::GpuSubInfo_Reader gpuSubInfo(j->ToBytes().data_, j->ToBytes().size_);
599             DataIndex categoryNameId = traceDataCache_->GetDataIndex(gpuSubInfo.category_name().ToStdString());
600             uint64_t size = gpuSubInfo.size();
601             uint32_t entryNum = gpuSubInfo.entry_num();
602             traceDataCache_->GetGpuWindowMemData()->AppendNewData(timeStamp, windowNameId, windowId, moduleNameId,
603                                                                   categoryNameId, size, entryNum, purgeableSize);
604         }
605     }
606 }
ParseGpuWindowMemInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const607 void HtraceMemParser::ParseGpuWindowMemInfo(const ProtoReader::MemoryData_Reader* tracePacket, uint64_t timeStamp) const
608 {
609     if (tracePacket->has_gpudumpinfo()) {
610         streamFilters_->statFilter_->IncreaseStat(TRACE_GPU_WINDOW_MEM, STAT_EVENT_RECEIVED);
611     }
612     for (auto i = tracePacket->gpudumpinfo(); i; ++i) {
613         ProtoReader::GpuDumpInfo_Reader GpuDumpInfo(i->ToBytes().data_, i->ToBytes().size_);
614         if (!GpuDumpInfo.has_gpu_detail_info()) {
615             continue;
616         }
617         FillGpuWindowMemInfo(GpuDumpInfo, timeStamp);
618     }
619 }
ParseWindowManagerServiceInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp)620 void HtraceMemParser::ParseWindowManagerServiceInfo(const ProtoReader::MemoryData_Reader* tracePacket,
621                                                     uint64_t timeStamp)
622 {
623     if (tracePacket->has_windowinfo()) {
624         streamFilters_->statFilter_->IncreaseStat(TRACE_WINDOW_MANAGER_SERVICE, STAT_EVENT_RECEIVED);
625     }
626     for (auto i = tracePacket->windowinfo(); i; ++i) {
627         ProtoReader::WindowManagerServiceInfo_Reader windowInfo(i->ToBytes().data_, i->ToBytes().size_);
628         if (!windowInfo.has_pid() || !windowInfo.has_window_name()) {
629             continue;
630         }
631         auto windowNameId = traceDataCache_->GetDataIndex(windowInfo.window_name().ToStdString());
632         auto ipid =
633             streamFilters_->processFilter_->GetOrCreateInternalPid(timeStamp, static_cast<uint32_t>(windowInfo.pid()));
634         windowIdToipidMap_.insert({windowNameId, ipid});
635     }
636 }
ParseCpuDumpInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const637 void HtraceMemParser::ParseCpuDumpInfo(const ProtoReader::MemoryData_Reader* tracePacket, uint64_t timeStamp) const
638 {
639     for (auto i = tracePacket->cpudumpinfo(); i; ++i) {
640         ProtoReader::CpuDumpInfo_Reader cpuDumpInfo(i->ToBytes().data_, i->ToBytes().size_);
641         auto totalSize = cpuDumpInfo.total_cpu_memory_size();
642         traceDataCache_->GetCpuDumpInfo()->AppendNewData(timeStamp, totalSize);
643     }
644 }
ParseProfileMemInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const645 void HtraceMemParser::ParseProfileMemInfo(const ProtoReader::MemoryData_Reader* tracePacket, uint64_t timeStamp) const
646 {
647     for (auto i = tracePacket->profilememinfo(); i; ++i) {
648         ProtoReader::ProfileMemInfo_Reader profileMemInfo(i->ToBytes().data_, i->ToBytes().size_);
649         auto channelIndex = traceDataCache_->GetDataIndex(profileMemInfo.channel().ToStdString());
650         auto totalSize = profileMemInfo.total_memory_size();
651         traceDataCache_->GetProfileMemInfo()->AppendNewData(timeStamp, channelIndex, totalSize);
652     }
653 }
654 
ParseRSImageDumpInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const655 void HtraceMemParser::ParseRSImageDumpInfo(const ProtoReader::MemoryData_Reader* tracePacket, uint64_t timeStamp) const
656 {
657     for (auto i = tracePacket->rsdumpinfo(); i; ++i) {
658         ProtoReader::RSImageDumpInfo_Reader rsImageDumpInfo(i->ToBytes().data_, i->ToBytes().size_);
659         auto size = rsImageDumpInfo.size();
660         auto typeIndex = traceDataCache_->GetDataIndex(rsImageDumpInfo.type().ToStdString());
661         InternalPid ipid = INVALID_IPID;
662         if (rsImageDumpInfo.has_pid()) {
663             ipid = streamFilters_->processFilter_->GetOrCreateInternalPid(timeStamp,
664                                                                           static_cast<uint32_t>(rsImageDumpInfo.pid()));
665         }
666         auto surfaceNameIndex = traceDataCache_->GetDataIndex(rsImageDumpInfo.surface_name().ToStdString());
667         traceDataCache_->GetRSImageDumpInfo()->AppendNewData(timeStamp, size, typeIndex, ipid, surfaceNameIndex);
668     }
669 }
ParseMemoryConfig(HtraceDataSegment & seg)670 void HtraceMemParser::ParseMemoryConfig(HtraceDataSegment& seg)
671 {
672     ProtoReader::MemoryConfig_Reader memConfigData(seg.protoData.data_, seg.protoData.size_);
673     if (memConfigData.has_pid()) {
674         bool parseError = false;
675         auto itor = memConfigData.pid(&parseError);
676         if (parseError) {
677             TS_LOGE("Parse pid in MemoryConfig function failed!!!");
678             return;
679         }
680         while (itor) {
681             int32_t pid = *itor;
682             auto ipid = streamFilters_->processFilter_->GetOrCreateInternalPid(seg.timeStamp, pid);
683             traceDataCache_->GetTraceConfigData()->AppendNewData("memory_config", "ipid", std::to_string(ipid));
684             itor++;
685         }
686     }
687 }
688 
Finish()689 void HtraceMemParser::Finish()
690 {
691     traceDataCache_->GetGpuWindowMemData()->RevicesIpid(windowIdToipidMap_);
692     if (traceDataCache_->traceStartTime_ == INVALID_UINT64 || traceDataCache_->traceEndTime_ == 0) {
693         traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime());
694     } else {
695         TS_LOGI("mem data time is not updated, maybe this trace file has other data");
696     }
697 }
698 } // namespace TraceStreamer
699 } // namespace SysTuning
700