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