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