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