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