• 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_->processMeasureFilter_->AppendNewMeasureData(
145             ipid, memNameDictMap_.at(MEM_PURG_SUM), timeStamp, processMemoryInfo.purg_sum_kb());
146     }
147     if (processMemoryInfo.has_purg_pin_kb()) {
148         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
149             ipid, memNameDictMap_.at(MEM_PURG_PIN), timeStamp, processMemoryInfo.purg_pin_kb());
150     }
151     if (processMemoryInfo.has_gl_pss_kb()) {
152         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
153             ipid, memNameDictMap_.at(MEM_GL_PSS), timeStamp, processMemoryInfo.gl_pss_kb());
154     }
155     if (processMemoryInfo.has_graph_pss_kb()) {
156         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
157             ipid, memNameDictMap_.at(MEM_GRAPH_PSS), timeStamp, processMemoryInfo.graph_pss_kb());
158     }
159     if (hasValue) {
160         streamFilters_->processFilter_->AddProcessMemory(ipid);
161     }
162     if (processMemoryInfo.has_smapinfo()) {
163         ParseSmapsInfoEasy(&processMemoryInfo, timeStamp, ipid);
164     }
165 }
166 
ParseProcessInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const167 void PbreaderMemParser::ParseProcessInfo(const ProtoReader::MemoryData_Reader *tracePacket, uint64_t timeStamp) const
168 {
169     if (tracePacket->has_processesinfo()) {
170         streamFilters_->statFilter_->IncreaseStat(TRACE_MEMORY, STAT_EVENT_RECEIVED);
171     }
172     for (auto i = tracePacket->processesinfo(); i; ++i) {
173         ProtoReader::ProcessMemoryInfo_Reader processMemoryInfo(i->ToBytes().data_, i->ToBytes().size_);
174         auto ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(
175             processMemoryInfo.pid(), processMemoryInfo.name().ToStdString());
176         uint32_t hasValue = 0;
177         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
178             ipid, memNameDictMap_.at(MEM_VM_SIZE), timeStamp, processMemoryInfo.vm_size_kb());
179         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
180             ipid, memNameDictMap_.at(MEM_VM_RSS), timeStamp, processMemoryInfo.vm_rss_kb());
181         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
182             ipid, memNameDictMap_.at(MEM_VM_ANON), timeStamp, processMemoryInfo.rss_anon_kb());
183         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
184             ipid, memNameDictMap_.at(MEM_RSS_FILE), timeStamp, processMemoryInfo.rss_file_kb());
185         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
186             ipid, memNameDictMap_.at(MEM_RSS_SHMEM), timeStamp, processMemoryInfo.rss_shmem_kb());
187         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
188             ipid, memNameDictMap_.at(MEM_VM_SWAP), timeStamp, processMemoryInfo.vm_swap_kb());
189         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
190             ipid, memNameDictMap_.at(MEM_VM_LOCKED), timeStamp, processMemoryInfo.vm_locked_kb());
191         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
192             ipid, memNameDictMap_.at(MEM_VM_HWM), timeStamp, processMemoryInfo.vm_hwm_kb());
193         hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(
194             ipid, memNameDictMap_.at(MEM_OOM_SCORE_ADJ), timeStamp, processMemoryInfo.oom_score_adj());
195 
196         SpecialDataAddition(processMemoryInfo, timeStamp, ipid, hasValue);
197     }
198 }
ParseSmapsPathTypeByPrefix(bool hasX,const std::string & path,const bool hasAppName) const199 uint32_t PbreaderMemParser::ParseSmapsPathTypeByPrefix(bool hasX, const std::string &path, const bool hasAppName) const
200 {
201     if (EndWith(path, ".so")) {
202         if (hasX) {
203             if (StartWith(path, "/data/app/") || hasAppName) {
204                 return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_CODE_APP);
205             } else {
206                 return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_CODE_SYS);
207             }
208         } else {
209             if (StartWith(path, "[anon:.bss]/data/app/") || StartWith(path, "/data/app/") || hasAppName) {
210                 return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_APP);
211             } else {
212                 return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_SYS);
213             }
214         }
215     }
216     return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_INVALID);
217 }
ParseSmapsPathTypeBySuffix(bool hasX,const std::string & path,const bool hasAppName) const218 uint32_t PbreaderMemParser::ParseSmapsPathTypeBySuffix(bool hasX, const std::string &path, const bool hasAppName) const
219 {
220     if ((EndWith(path, ".jar")) || (EndWith(path, ".apk")) || (EndWith(path, ".vdex")) || (EndWith(path, ".odex")) ||
221         (EndWith(path, ".oat")) || (path.find("dex") != std::string::npos)) {
222         return hasX ? (hasAppName ? static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_CODE_APP)
223                                   : static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_CODE_SYS))
224                     : (hasAppName ? static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_APP)
225                                   : static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_SYS));
226     }
227     return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_INVALID);
228 }
229 
ParseSmapsBlockDetail(ProtoReader::SmapsInfo_Reader & smapsInfo,const std::string & path,const bool hasAppName) const230 uint32_t PbreaderMemParser::ParseSmapsBlockDetail(ProtoReader::SmapsInfo_Reader &smapsInfo,
231                                                   const std::string &path,
232                                                   const bool hasAppName) const
233 {
234     bool hasX = smapsInfo.permission().ToStdString().find("x") != std::string::npos;
235     auto type = ParseSmapsPathTypeByPrefix(hasX, path, hasAppName);
236     if (type != static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_INVALID)) {
237         return type;
238     }
239     type = ParseSmapsPathTypeBySuffix(hasX, path, hasAppName);
240     if (type != static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_INVALID)) {
241         return type;
242     }
243     if (hasX && path.find("/bin/") != std::string::npos) {
244         return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_CODE_SYS);
245     }
246     if ((!hasX) && (path.find("/bin/") != std::string::npos || path.find("[anon:.bss]") != std::string::npos)) {
247         return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_SYS);
248     }
249     if (path.find("[bss]") != std::string::npos) {
250         return hasAppName ? static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_APP)
251                           : static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_DATA_SYS);
252     }
253     if ((path.find("[anon]") != std::string::npos) || (path.find("[anon:") != std::string::npos)) {
254         if (std::find(g_unknownAnonMemInfo.begin(), g_unknownAnonMemInfo.end(), path) != g_unknownAnonMemInfo.end()) {
255             return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_UNKNOWN_ANON);
256         }
257         return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_NATIVE_HEAP);
258     }
259     return static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_INVALID);
260 }
261 
ParseSmapsBlockType(ProtoReader::SmapsInfo_Reader & smapsInfo) const262 uint32_t PbreaderMemParser::ParseSmapsBlockType(ProtoReader::SmapsInfo_Reader &smapsInfo) const
263 {
264     std::string path(smapsInfo.path().ToStdString());
265     path.erase(0, path.find_first_not_of(" "));
266     path.erase(path.find_last_not_of(" ") + 1);
267     if (path.empty()) {
268         path = "[anon]";
269     }
270     for (const auto &iter : g_checkMemStart) {
271         if (StartWith(path, iter.first)) {
272             return iter.second;
273         }
274     }
275     for (const auto &iter : g_checkMemEnd) {
276         if (EndWith(path, iter.first)) {
277             return iter.second;
278         }
279     }
280     for (const auto &iter : g_checkMemContain) {
281         if (path.find(iter.first) != std::string::npos) {
282             return iter.second;
283         }
284     }
285     bool hasAppName = path.find("com.huawei.wx") != std::string::npos;
286     uint32_t detailRet = ParseSmapsBlockDetail(smapsInfo, path, hasAppName);
287     if (detailRet != static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_INVALID)) {
288         return detailRet;
289     }
290     return hasAppName ? static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_OTHER_APP)
291                       : static_cast<uint32_t>(SmapsMemType::SMAPS_MEM_TYPE_OTHER_SYS);
292 }
293 
ParseSmapsInfoEasy(const ProtoReader::ProcessMemoryInfo_Reader * memInfo,uint64_t timeStamp,uint64_t ipid) const294 void PbreaderMemParser::ParseSmapsInfoEasy(const ProtoReader::ProcessMemoryInfo_Reader *memInfo,
295                                            uint64_t timeStamp,
296                                            uint64_t ipid) const
297 {
298     streamFilters_->statFilter_->IncreaseStat(TRACE_SMAPS, STAT_EVENT_RECEIVED);
299     for (auto i = memInfo->smapinfo(); i; ++i) {
300         SmapsRow row;
301         row.timeStamp = timeStamp;
302         row.ipid = ipid;
303         ProtoReader::SmapsInfo_Reader smapsInfo(i->ToBytes().data_, i->ToBytes().size_);
304         row.startAddr = "0x" + smapsInfo.start_addr().ToStdString();
305         row.endAddr = "0x" + smapsInfo.end_addr().ToStdString();
306         row.dirty = smapsInfo.dirty();
307         row.swapper = smapsInfo.swapper();
308         row.rss = smapsInfo.rss();
309         row.pss = smapsInfo.pss();
310         row.size = smapsInfo.size();
311         row.reside = smapsInfo.reside();
312         row.protectionId = traceDataCache_->GetDataIndex(smapsInfo.permission().ToStdString());
313         row.pathId = traceDataCache_->GetDataIndex(smapsInfo.path().ToStdString());
314         row.sharedClean = smapsInfo.has_private_clean() ? smapsInfo.private_clean() : 0;
315         row.sharedDirty = smapsInfo.has_private_dirty() ? smapsInfo.private_dirty() : 0;
316         row.privateClean = smapsInfo.has_shared_clean() ? smapsInfo.shared_clean() : 0;
317         row.privateDirty = smapsInfo.has_shared_dirty() ? smapsInfo.shared_dirty() : 0;
318         row.swap = smapsInfo.has_swap() ? smapsInfo.swap() : 0;
319         row.swapPss = smapsInfo.has_swap_pss() ? smapsInfo.swap_pss() : 0;
320         row.type = ParseSmapsBlockType(smapsInfo);
321         traceDataCache_->GetSmapsData()->AppendNewData(row);
322     }
323 }
324 
ParseMemInfoEasy(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const325 void PbreaderMemParser::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 PbreaderMemParser::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 PbreaderMemParser::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 PbreaderMemParser::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 PbreaderMemParser::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     AshMemRow row;
396     row.ts = timeStamp;
397     for (auto i = tracePacket->ashmeminfo(); i; ++i) {
398         ProtoReader::AshmemInfo_Reader AshmemInfo(i->ToBytes().data_, i->ToBytes().size_);
399         row.ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(AshmemInfo.pid(),
400                                                                                  AshmemInfo.name().ToStdString());
401         row.adj = AshmemInfo.adj();
402         row.fd = AshmemInfo.fd();
403         row.ashmemNameId = traceDataCache_->GetDataIndex(AshmemInfo.ashmem_name().ToStdString());
404         row.size = AshmemInfo.size();
405         row.ashmemId = AshmemInfo.id();
406         row.time = AshmemInfo.time();
407         row.refCount = AshmemInfo.ref_count();
408         row.purged = AshmemInfo.purged();
409         row.flag = 0;
410         row.pss = 0;
411         auto smapsData = traceDataCache_->GetConstSmapsData();
412         auto smapsCount = smapsData.Size();
413         for (auto j = 0; j < smapsCount; j++) {
414             auto path = traceDataCache_->GetDataFromDict(smapsData.PathIds()[j]);
415             if ((smapsData.Ipids()[j] == row.ipid) && (path.find("/dev/ashmem/") != std::string::npos)) {
416                 row.pss += smapsData.Pss()[j] + smapsData.SwapPss()[j];
417             }
418         }
419         traceDataCache_->GetAshMemData()->AppendNewData(row);
420     }
421     AshMemDeduplicate();
422 }
AshMemDeduplicate() const423 void PbreaderMemParser::AshMemDeduplicate() const
424 {
425     auto ashMemData = traceDataCache_->GetAshMemData();
426     auto ashMemCount = ashMemData->Size();
427     if (ashMemCount <= 1) {
428         return;
429     }
430 
431     std::vector<std::pair<size_t, size_t>> dataByTs;
432     size_t start = 0;
433     auto ts = ashMemData->TimeStampData()[0];
434     for (auto i = 0; i < ashMemCount; ++i) {
435         auto tsTmp = ashMemData->TimeStampData()[i];
436         if (tsTmp != ts) {
437             dataByTs.emplace_back(std::make_pair(start, i - 1));
438             start = i;
439             ts = tsTmp;
440         }
441     }
442     dataByTs.emplace_back(std::make_pair(start, ashMemCount - 1));
443 
444     for (const auto &iterator : dataByTs) {
445         /* L1 map (key = id+time, value = L2 map)
446            L2 map (key = ipid, value = index) */
447         std::map<std::pair<uint32_t, uint64_t>, std::map<uint64_t, uint64_t>> AshMemMap;
448         for (auto i = iterator.first; i <= iterator.second; ++i) {
449             auto ashmemId = ashMemData->AshmemIds()[i];
450             auto time = ashMemData->Times()[i];
451             auto key = std::make_pair(ashmemId, time);
452             auto ipid = ashMemData->Ipids()[i];
453             auto &pidMap = AshMemMap[key];
454             if (pidMap.find(ipid) == pidMap.end()) {
455                 pidMap.emplace(ipid, i);
456             } else {
457                 ashMemData->SetFlag(i, (uint32_t)MemDeduplicateFlag::MEM_DEDUPLICATE_FLAG_DUP_SAME_PROCESS);
458             }
459         }
460 
461         for (const auto &item : AshMemMap) {
462             auto &pidMap = item.second;
463             auto iter = pidMap.begin();
464             if (iter == pidMap.end()) {
465                 continue;
466             }
467             for (++iter; iter != pidMap.end(); ++iter) {
468                 ashMemData->SetFlag(iter->second, (uint32_t)MemDeduplicateFlag::MEM_DEDUPLICATE_FLAG_DUP_DIFF_PROCESS);
469             }
470         }
471     }
472 }
GetMemProcessType(uint64_t ipid) const473 PbreaderMemParser::MemProcessType PbreaderMemParser::GetMemProcessType(uint64_t ipid) const
474 {
475     const auto &iterProcess = traceDataCache_->GetConstProcessData(ipid);
476     if (iterProcess.cmdLine_ == "composer_host") {
477         return MemProcessType::PID_TYPE_COMPOSER;
478     } else if (iterProcess.cmdLine_ == "render_service") {
479         return MemProcessType::PID_TYPE_RENDER_SERVICES;
480     } else {
481         return MemProcessType::PID_TYPE_APP;
482     }
483 }
484 
ParseDmaMemInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const485 void PbreaderMemParser::ParseDmaMemInfo(const ProtoReader::MemoryData_Reader *tracePacket, uint64_t timeStamp) const
486 {
487     if (tracePacket->has_dmainfo()) {
488         streamFilters_->statFilter_->IncreaseStat(TRACE_DMAMEM, STAT_EVENT_RECEIVED);
489     }
490     for (auto i = tracePacket->dmainfo(); i; ++i) {
491         ProtoReader::DmaInfo_Reader DmaMemInfo(i->ToBytes().data_, i->ToBytes().size_);
492         DmaMemRow row;
493         row.ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(DmaMemInfo.pid(),
494                                                                                  DmaMemInfo.name().ToStdString());
495         row.ts = timeStamp;
496         row.fd = DmaMemInfo.fd();
497         row.size = DmaMemInfo.size();
498         row.ino = DmaMemInfo.ino();
499         row.expPid = DmaMemInfo.exp_pid();
500         row.expTaskCommId = traceDataCache_->GetDataIndex(DmaMemInfo.exp_task_comm().ToStdString());
501         row.bufNameId = traceDataCache_->GetDataIndex(DmaMemInfo.buf_name().ToStdString());
502         row.expNameId = traceDataCache_->GetDataIndex(DmaMemInfo.exp_name().ToStdString());
503         row.flag = 0;
504         traceDataCache_->GetDmaMemData()->AppendNewData(row);
505     }
506     DmaMemDeduplicate();
507 }
DmaMemDeduplicate() const508 void PbreaderMemParser::DmaMemDeduplicate() const
509 {
510     auto dmaMemData = traceDataCache_->GetDmaMemData();
511     auto dmaCount = dmaMemData->Size();
512     if (dmaCount <= 1) {
513         return;
514     }
515 
516     std::vector<std::pair<size_t, size_t>> dataByTs;
517     size_t start = 0;
518     auto ts = dmaMemData->TimeStampData()[0];
519     for (auto i = 0; i < dmaCount; ++i) {
520         auto tsTmp = dmaMemData->TimeStampData()[i];
521         if (tsTmp != ts) {
522             dataByTs.emplace_back(std::make_pair(start, i - 1));
523             start = i;
524             ts = tsTmp;
525         }
526     }
527     dataByTs.emplace_back(std::make_pair(start, dmaCount - 1));
528 
529     for (const auto &iterator : dataByTs) {
530         /* L1 map (key = ino, value = L2 map)
531            L2 map (key = ipid, value = pair(index, MemProcessType)) */
532         std::map<uint32_t, std::map<uint64_t, std::pair<uint64_t, MemProcessType>>> inoMap;
533         std::map<uint32_t /*ino*/, MemProcessType> processTypeMap;
534         for (auto i = iterator.first; i <= iterator.second; ++i) {
535             auto ino = dmaMemData->Inos()[i];
536             auto ipid = dmaMemData->Ipids()[i];
537             auto &pidMap = inoMap[ino];
538             if (pidMap.find(ipid) != pidMap.end()) {
539                 dmaMemData->SetFlag(i, (uint32_t)MemDeduplicateFlag::MEM_DEDUPLICATE_FLAG_DUP_SAME_PROCESS);
540             } else {
541                 auto processType = GetMemProcessType(ipid);
542                 pidMap.emplace(ipid, std::make_pair(i, processType));
543                 if (processTypeMap[ino] < processType) {
544                     processTypeMap[ino] = processType;
545                 }
546             }
547         }
548 
549         for (const auto &item : inoMap) {
550             auto maxPidType = processTypeMap[item.first];
551             const auto &pidMap = item.second;
552             for (const auto &pidItem : pidMap) {
553                 if (pidItem.second.second < maxPidType) {
554                     dmaMemData->SetFlag(pidItem.second.first,
555                                         (uint32_t)MemDeduplicateFlag::MEM_DEDUPLICATE_FLAG_DUP_DIFF_PROCESS);
556                 }
557             }
558         }
559     }
560 }
561 
ParseGpuProcessMemInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const562 void PbreaderMemParser::ParseGpuProcessMemInfo(const ProtoReader::MemoryData_Reader *tracePacket,
563                                                uint64_t timeStamp) const
564 {
565     if (tracePacket->has_gpumemoryinfo()) {
566         streamFilters_->statFilter_->IncreaseStat(TRACE_GPU_PROCESS_MEM, STAT_EVENT_RECEIVED);
567     }
568     for (auto i = tracePacket->gpumemoryinfo(); i; ++i) {
569         ProtoReader::GpuMemoryInfo_Reader GpuMemoryInfo(i->ToBytes().data_, i->ToBytes().size_);
570         DataIndex gpuNameId = traceDataCache_->GetDataIndex(GpuMemoryInfo.gpu_name().ToStdString());
571         uint64_t allGpuSize = GpuMemoryInfo.all_gpu_size();
572         if (GpuMemoryInfo.has_gpu_process_info()) {
573             for (auto j = GpuMemoryInfo.gpu_process_info(); j; ++j) {
574                 ProtoReader::GpuProcessInfo_Reader GpuProcessInfo(j->ToBytes().data_, j->ToBytes().size_);
575                 GpuProcessMemRow row;
576                 row.ts = timeStamp;
577                 row.gpuNameId = gpuNameId;
578                 row.allGpuSize = allGpuSize;
579                 row.addr = GpuProcessInfo.addr().ToStdString();
580                 uint32_t pid = GpuProcessInfo.pid();
581                 uint32_t tid = GpuProcessInfo.tid();
582                 row.itid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(tid, pid);
583                 row.ipid = streamFilters_->processFilter_->GetOrCreateInternalPid(timeStamp, pid);
584                 row.usedGpuSize = GpuProcessInfo.used_gpu_size();
585                 traceDataCache_->GetGpuProcessMemData()->AppendNewData(row);
586             }
587         }
588     }
589 }
FillGpuWindowMemInfo(const ProtoReader::GpuDumpInfo_Reader & gpuDumpInfo,uint64_t timeStamp) const590 void PbreaderMemParser::FillGpuWindowMemInfo(const ProtoReader::GpuDumpInfo_Reader &gpuDumpInfo,
591                                              uint64_t timeStamp) const
592 {
593     DataIndex windowNameId = traceDataCache_->GetDataIndex(gpuDumpInfo.window_name().ToStdString());
594     GpuWindowMemRow row;
595     row.windowNameId = windowNameId;
596     row.ts = timeStamp;
597     row.windowId = gpuDumpInfo.id();
598     row.purgeableSize = gpuDumpInfo.gpu_purgeable_size();
599     for (auto i = gpuDumpInfo.gpu_detail_info(); i; ++i) {
600         ProtoReader::GpuDetailInfo_Reader GpuDetailInfo(i->ToBytes().data_, i->ToBytes().size_);
601         row.moduleNameId = traceDataCache_->GetDataIndex(GpuDetailInfo.module_name().ToStdString());
602         if (!GpuDetailInfo.has_gpu_sub_info()) {
603             continue;
604         }
605         for (auto j = GpuDetailInfo.gpu_sub_info(); j; ++j) {
606             ProtoReader::GpuSubInfo_Reader gpuSubInfo(j->ToBytes().data_, j->ToBytes().size_);
607 
608             row.categoryNameId = traceDataCache_->GetDataIndex(gpuSubInfo.category_name().ToStdString());
609             row.size = gpuSubInfo.size();
610             row.count = gpuSubInfo.entry_num();
611             traceDataCache_->GetGpuWindowMemData()->AppendNewData(row);
612         }
613     }
614 }
ParseGpuWindowMemInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const615 void PbreaderMemParser::ParseGpuWindowMemInfo(const ProtoReader::MemoryData_Reader *tracePacket,
616                                               uint64_t timeStamp) const
617 {
618     if (tracePacket->has_gpudumpinfo()) {
619         streamFilters_->statFilter_->IncreaseStat(TRACE_GPU_WINDOW_MEM, STAT_EVENT_RECEIVED);
620     }
621     for (auto i = tracePacket->gpudumpinfo(); i; ++i) {
622         ProtoReader::GpuDumpInfo_Reader GpuDumpInfo(i->ToBytes().data_, i->ToBytes().size_);
623         if (!GpuDumpInfo.has_gpu_detail_info()) {
624             continue;
625         }
626         FillGpuWindowMemInfo(GpuDumpInfo, timeStamp);
627     }
628 }
ParseWindowManagerServiceInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp)629 void PbreaderMemParser::ParseWindowManagerServiceInfo(const ProtoReader::MemoryData_Reader *tracePacket,
630                                                       uint64_t timeStamp)
631 {
632     if (tracePacket->has_windowinfo()) {
633         streamFilters_->statFilter_->IncreaseStat(TRACE_WINDOW_MANAGER_SERVICE, STAT_EVENT_RECEIVED);
634     }
635     for (auto i = tracePacket->windowinfo(); i; ++i) {
636         ProtoReader::WindowManagerServiceInfo_Reader windowInfo(i->ToBytes().data_, i->ToBytes().size_);
637         if (!windowInfo.has_pid() || !windowInfo.has_window_name()) {
638             continue;
639         }
640         auto windowNameId = traceDataCache_->GetDataIndex(windowInfo.window_name().ToStdString());
641         auto ipid =
642             streamFilters_->processFilter_->GetOrCreateInternalPid(timeStamp, static_cast<uint32_t>(windowInfo.pid()));
643         windowIdToipidMap_.insert({windowNameId, ipid});
644     }
645 }
ParseCpuDumpInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const646 void PbreaderMemParser::ParseCpuDumpInfo(const ProtoReader::MemoryData_Reader *tracePacket, uint64_t timeStamp) const
647 {
648     for (auto i = tracePacket->cpudumpinfo(); i; ++i) {
649         ProtoReader::CpuDumpInfo_Reader cpuDumpInfo(i->ToBytes().data_, i->ToBytes().size_);
650         auto totalSize = cpuDumpInfo.total_cpu_memory_size();
651         traceDataCache_->GetCpuDumpInfo()->AppendNewData(timeStamp, totalSize);
652     }
653 }
ParseProfileMemInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const654 void PbreaderMemParser::ParseProfileMemInfo(const ProtoReader::MemoryData_Reader *tracePacket, uint64_t timeStamp) const
655 {
656     for (auto i = tracePacket->profilememinfo(); i; ++i) {
657         ProtoReader::ProfileMemInfo_Reader profileMemInfo(i->ToBytes().data_, i->ToBytes().size_);
658         auto channelIndex = traceDataCache_->GetDataIndex(profileMemInfo.channel().ToStdString());
659         auto totalSize = profileMemInfo.total_memory_size();
660         traceDataCache_->GetProfileMemInfo()->AppendNewData(timeStamp, channelIndex, totalSize);
661     }
662 }
663 
ParseRSImageDumpInfo(const ProtoReader::MemoryData_Reader * tracePacket,uint64_t timeStamp) const664 void PbreaderMemParser::ParseRSImageDumpInfo(const ProtoReader::MemoryData_Reader *tracePacket,
665                                              uint64_t timeStamp) const
666 {
667     for (auto i = tracePacket->rsdumpinfo(); i; ++i) {
668         ProtoReader::RSImageDumpInfo_Reader rsImageDumpInfo(i->ToBytes().data_, i->ToBytes().size_);
669         auto size = rsImageDumpInfo.size();
670         auto typeIndex = traceDataCache_->GetDataIndex(rsImageDumpInfo.type().ToStdString());
671         InternalPid ipid = INVALID_IPID;
672         if (rsImageDumpInfo.has_pid()) {
673             ipid = streamFilters_->processFilter_->GetOrCreateInternalPid(timeStamp,
674                                                                           static_cast<uint32_t>(rsImageDumpInfo.pid()));
675         }
676         auto surfaceNameIndex = traceDataCache_->GetDataIndex(rsImageDumpInfo.surface_name().ToStdString());
677         traceDataCache_->GetRSImageDumpInfo()->AppendNewData(timeStamp, size, typeIndex, ipid, surfaceNameIndex);
678     }
679 }
ParseMemoryConfig(PbreaderDataSegment & seg)680 void PbreaderMemParser::ParseMemoryConfig(PbreaderDataSegment &seg)
681 {
682     ProtoReader::MemoryConfig_Reader memConfigData(seg.protoData.data_, seg.protoData.size_);
683     if (memConfigData.has_pid()) {
684         bool parseError = false;
685         auto itor = memConfigData.pid(&parseError);
686         if (parseError) {
687             TS_LOGE("Parse pid in MemoryConfig function failed!!!");
688             return;
689         }
690         while (itor) {
691             int32_t pid = *itor;
692             auto ipid = streamFilters_->processFilter_->GetOrCreateInternalPid(seg.timeStamp, pid);
693             traceDataCache_->GetTraceConfigData()->AppendNewData("memory_config", "ipid", std::to_string(ipid));
694             itor++;
695         }
696     }
697 }
698 
Finish()699 void PbreaderMemParser::Finish()
700 {
701     traceDataCache_->GetGpuWindowMemData()->RevicesIpid(windowIdToipidMap_);
702     if (traceDataCache_->traceStartTime_ == INVALID_UINT64 || traceDataCache_->traceEndTime_ == 0) {
703         traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime());
704     } else {
705         TS_LOGI("mem data time is not updated, maybe this trace file has other data");
706     }
707 }
708 } // namespace TraceStreamer
709 } // namespace SysTuning
710