native堆-通过工具分析内存占用

来源飞书 wiki(obj_token: Pv4PdhWwtocurDxZA5WcBtSInhd)

⚠️ 28 张内嵌图片均为飞书内部 authcode 鉴权图(media_download 返回 403/404),无法通过 MCP 下载。已就地转为”图片描述”引用块,保留原文 alt 文本与 image token 供溯源。

native堆-通过工具分析内存占用

展示报告内容介绍:

📷 图片描述: 图片展示的是一个文件夹内容界面,文件夹名为”systemui_rss_values_systemui_traces_SM8850_vs_SM8750_vs_fake1_vs_fake2_native”。界面中显示了多个文件夹,包括”fire_html""trace""csv""plots”等,均为2026年1月6日9:41创建,大小均为0。此外,还显示了”native_all_iters_peak_rss_comparison.html”文件,创建于2026年1月5日22:55,大小为4,632 KB。该图片与文档中展示报告内容相关,呈现了报告中涉及的文件夹及文件信息。(token: ZYLYbkDxIoffy7xkbMWcv1otnVd

📷 图片描述: 图片展示的是电脑文件夹中的内容,文件夹名为”systemserver_pss > csv”。文件夹内有多个文件,其中”showmap”文件夹被红框突出显示。该图片与文档中分析native堆内存占用的上下文相关,可能是用于说明在进行内存占用分析时,从系统服务器pss文件夹下的csv文件夹中找到的”showmap”文件夹,该文件夹可能包含用于支撑html解析生成csv的原始数据。(token: OBI5bHxAfoRhpOx6pgPcfvIUnih

plots业务可以不用关注,它的用处主要用于支撑下面html解析生成

csv下面有个 showmap原始数据文件夹

  1. native_all_iters_peak_rss_comparison.html文件内容解读

总览:

三轮showmap数据曲线图:

不用关注fake1和fake2,测试工具需要对比4个机型的数据,因为当前只比较两个,所以mock两个假数据。

📷 图片描述: 图片展示的是systemui内存对比数据,标题为”systemui内存对比:mi8850 vs vivo8750 vs fake1 vs fake2”。图中呈现了多轮内存测试情况,横轴为Ref1、Ref2、Ref3,纵轴为RSS(KB)。曲线分别代表mi8850、vivo8750、fake1、fake2的Peak RSS。其中,mi8850的曲线最高,vivo8750的曲线最低,fake1和fake2的曲线相近。该图与上下文关系紧密,是对上文提及的三轮showmap数据曲线图的展示,用于对比不同设备的内存使用情况。(token: RoWYbVP8ModYwLxJdo4cZghpnub

单轮数据:

单轮showmap曲线

从三轮数据中选取最接近均值的一轮,作为分析对象

showmap数据的抓取从测试开始到测试结束全程抓取,可以理解成不断的抓showmap数据

📷 图片描述: 图片展示了单轮内存测试情况,包含三轮showmap数据曲线图和单轮showmap曲线图。左侧图中,不同机型的内存RSS值随轮次变化,如m8600、m8600_1等。右侧图是单轮数据对比,同样显示不同机型内存RSS值变化,有红色箭头指向关键数据点。下方表格列出各类别内存RSS差值对比,如m8600与m8600_1等机型的差值。该图与上下文关系紧密,直观呈现了内存测试数据,辅助分析内存占用情况。(token: N0lqbKJF8ol4XXx0tCNcUrLvnHc

左侧表:测试机和对比机都是第一轮数据接近均值,所以选出作为分析。

右侧表:过滤具体场景,比如当前是native匿名页,这里边可以看到测试开始时当前进程已经有20MB的内存了。

最下面的showmap_86 作为结束时的showmap数据,showmap 拆分就是基于该文件

分场景比较内存:

可以对比看 native堆/java堆内存差异,文件页差异等,下面的三个表可以具体展开看更细力度的数据

📷 图片描述: 图片展示的是分场景比较内存的表格数据,包含线程数、匿名页 - Java、匿名页 - Native、匿名页 - 其他、文件页、其他等类别,以及mi8850、vivo8750、take1、take2等不同测试对象的数据。表格分为文件页细分表、匿名页 - 其他 细分表、showmap 详情对比三部分。该表格与上下文关系紧密,用于对比native堆/java堆内存差异等,是分析内存占用情况的重要数据来源。(token: UoETbQCJsoidX3xujOocM54znhb

java堆/native堆 文件页过滤规则

📷 图片描述: 图片展示的是一个代码编辑界面,显示了名为”showmap_no_diff.py”的Python脚本代码。代码中定义了”parse_diff_data”函数,用于解析不同数据文件。代码通过if语句判断字符串y_str的前缀,以确定其类别,如”测试""测试1""测试2”等,还对”anon:""anon:android""anon:android:“等特定前缀进行处理。该图片与文档中”分场景比较内存”部分相关,用于说明文件中对不同场景数据的解析逻辑。(token: YrDRbAdZWooTQYxvbhAcpX0OnCb

📷 图片描述: 图片是用于对比java堆/native堆文件页差异的文件页细分表。表中列出了不同文件类型(如*.so、*.jar等)在不同测试机(m18880、vivoX750等)上的计数数据,还包含各测试机数据的差值(如vivoX750 - m18880等)。表格底部有统计总和及占比数据。该表与文档中”分场景比较内存”部分的内容相关,可用于更细力度地查看java堆/native堆文件页的差异情况,辅助分析内存占用。(token: Qkcmb1V5povgZnxcVTecnAoAnif

native堆问题分析方法

通过自研工具(mem use)抓获的内存数据可以明确的指出方法分配内存的大小,通过跟对比机比较相同函数内存差值,可以快速的定位问题。

📷 图片描述: 图片展示了Native堆拆解界面,包含库维度对比和函数维度对比两个部分。库维度对比以单位KB为单位,函数维度对比同样以单位KB为单位。该图片与文档中”Native堆问题分析方法”部分内容相关,用于说明在分析Native堆问题时,可通过库维度和函数维度对比,找到差异所在,进而找到具体申请内存的函数,为后续通过perfetto查看调用栈等操作提供数据基础。(token: UlB3bIPSAoGDKxx0Ha3ceD5qnZe

可以先从库维度看下,差异在哪里

📷 图片描述: 图片展示的是SM8850和SM8750两个版本的内存占用对比数据。表格包含libname、SM8850_iter2_count、SM8750_iter2_count、count_diff_SM8850_iter2_vs_SM8750_iter2、SM8850_iter2_size、SM8750_iter2_size、size_diff_SM8850_iter2_vs_SM8750_iter2等列。其中,libname列显示了多个库文件名称,如libhwui.so、libvulkan_adreno.so等;count_diff列显示了两版本间库文件数量差异,如libhwui.so差异为41640.608;size_diff列显示了两版本间库文件大小差异,如libhwui.so差异为-21000.304。该图用于分析库维度内存占用差异。(token: N3JJbsTqxoWYWBxm578cLDFonDA

函数维度,找到具体申请内存的函数

📷 图片描述: 图片展示的是通过工具分析内存占用时,函数维度找到具体申请内存的函数结果。表格中列出了函数名、函数大小、函数大小变化等信息,如total、android.graphics.BitmapCache等函数的大小及变化情况。其中,函数大小变化部分以红色突出显示,如android.graphics.BitmapCache大小变化为10198.62KB,android.graphics.BitmapCache@10000000大小变化为10198.62KB。该图片与上文提到的函数维度分析内存占用相呼应,直观呈现了具体函数的内存占用情况。(token: TWevbT1WvozNlMxXRdPcV2aNn4k

通过perfetto查看具体的调用栈

📷 图片描述: 图片展示了在浏览器中下载的”systemui_rss_values_systemui_traces_SM8850_vs_SM8750_vs_fake1_vs_fake2_native”文件夹内容。文件夹内有两个PFTRACE文件,分别为”systemui_SM8750_20260105_202504_iter1_merged_all_perfetto.pftrace”和”systemui_SM8850_20260105_221201_iter1_merged_all_perfetto.pftrace”,修改日期均为2026/1/5 22:53,大小分别为60,657 KB和90,696 KB。图片中”trace”部分被红色框突出显示,与文档中”通过perfetto查看具体的调用栈”上下文相关,表明这些文件是用于分析内存占用问题的perfetto数据文件。(token: Hzjcb99PAohJ4UxiKFMcZSTUni0

内存工具提供的perfetto,必须通过该网址打开 https://perfetto.loadterminator.mioffice.cn/

该工具有使用问题可以联系

📷 图片描述: 图片展示了Perfetto工具中”Plugins”页面。左侧导航栏选中”Plugins”。右侧”PLUGINS”区域有”Restore Defaults”和”Reload required”按钮,以及”Sort by Name”和”Search…”搜索框。下方列出了多个插件选项,如”MemoryAnalyzer""PowerAnalyzer”等,其中”MemoryAnalyzer”被红色框突出显示并有红色箭头指向,表明其为关键插件。该图片与文档中”通过perfetto查看具体的调用栈”部分相关,用于说明在Perfetto中开启MemoryAnalyzer插件以进行内存占用分析。(token: W34GblqYWoiszWxIpbgcECRYnuh

📷 图片描述: 图片展示的是内存工具相关数据表格,标题为”Table Memory Func Name Aggregation(1023)“。表格中列出了多个函数名(func_name),如vkCreatePipelineCache、android::SkiaCodec::set等,以及对应的库名(如libvulkan.so、libhwui.so等)、total_count(调用总次数)和total_mem(总内存占用)等信息。其中,total_mem列数据较为关键,显示了每个函数的内存占用数值。该图片与上文提到的从函数维度找到具体申请内存的函数相关,可用于native堆内存占用分析。(token: XBrTbggzioRl0UxBfSGcTBFKnpp

📷 图片描述: 图片展示的是内存工具提供的Perfetto中火焰图分析界面。界面中”Table Memory Slice”标签被选中,右侧显示了内存占用相关信息,如slice_id、dur、arg_set_id、mem_size、func_name等。右侧还有”Sort”选项,可按最高或最低排序。下方有”Add filter”下拉菜单,可设置过滤条件,如”equals to""not equals to”等,当前选中”equals to”并输入”al::vkCreatePipelineCache”。该图片与文档中”通过perfetto查看具体的调用栈”内容相关,用于辅助分析内存占用问题。(token: Y1lnbvNrEo1KYKxPjEecPvl5nMb

📷 图片描述: 图片展示的是通过perfetto查看native堆内存占用时的火焰图分析界面。界面中以表格形式呈现了内存占用信息,包括func_name、func_id、arg_set_id、mem_size、func_name、lib_name等字段。红色框突出显示了stacktrace信息,记录了内存申请的具体函数和库文件,如”vulkan_adreno.so”等,以及对应的函数名”vkCreatePipelineCache”等。该图片与文档中通过perfetto查看具体的调用栈的内容相关,用于辅助分析内存占用问题。(token: Qb7HbYOgSoUFmMxsiYIciPo8nbX

相关文档:内存工具-内存占用分析Systemui 开机native内存占用分析

Perfetto 功能补充 @钟万勇

📷 图片描述: 图片展示的是通过Perfetto查看native堆内存占用的火焰图。上方是时间轴,显示了从12:00:00到12:00:02的时间段。中间部分以不同颜色条块呈现函数调用情况,下方表格列出函数名称、函数地址、函数大小等信息。红色框突出显示了”mciCreateFunctionCache”函数,其函数大小为10780字节,函数地址为0x400296。该图片与文档中通过Perfetto查看具体调用栈的内容相关,用于辅助分析native堆内存占用问题。(token: CmxZbvg91o2EagxHM1KcbmmqnTe

火焰图查看

📷 图片描述: 图片展示了内存工具抓取的火焰图文件夹内容。文件夹内有多个文件夹和文件,其中”fire_html”和”simpleperf_html”文件夹被红色数字序号①②标注,分别对应火焰图抓取的两种方式。该图片与文档中”火焰图查看”部分内容相关,说明了通过内存工具抓取的火焰图提供了两种数据获取方式,可用于分析内存占用情况。(token: PYZzbVjxWorUtBxlh9wcQTPknUa

提供了两种方式抓取的火焰图①②都可用于分析,数据获取方式不同。

①是内存采集工具(mem use) hook抓取的内存信息数据转成的火焰图(数据精准,实际内存使用的大小,可能存在调用栈层级少的情况)

②是simpleperf抓取时加了内存参数,解析出来的结果(调用栈回栈信息更全,只包含malloc,不包含free的内存

chrt -f 10 simpleperf record -g -p {pids_str} --duration 30 -e kmem:mm_page_alloc -c 1 -m {simple_buf} --cpu-percent 99 --user-buffer-size 1536M -o {outfile}

📷 图片描述: 图片展示了在文件夹”systemui_rss_values_systemui_traces_SM8850_vs_SM8750_vs_fake1_vs_fake2_native”下,memuse_report文件的相关内容。其中,memuse_report_SM8850_iter1.html和memuse_report_SM8750_iter1.html是html文件,memuse_report_SM8850_iter1.json和memuse_report_SM8750_iter1.json是json源文件。图片中”fire_html”部分用红色框突出显示,与上下文提到的”对比火焰图通过该网址打开:https://test.loadterminator.mioffice.cn/#/flamegraph/demo”相呼应,表明这些文件是用于对比火焰图的base数据格式化后的json文件。(token: Gr4Qb1Bszomo5DxKkUDc85rWnCh

内存火焰图查看调用栈:

📷 图片描述: 图片展示的是内存火焰图分析image_id对应的内存占用。上方有”Chart Statistics""Sample Table""Flamegraph”选项卡,当前选中”Chart Statistics”。下方显示记录时间为2026 - 01 - 05 22:54:51,机器类型为aarch64,总样本数为1090120,事件类型为memory,进程为14131(14131)。右侧有”Back”按钮。下方饼图显示了进程14131的内存占用分布。(token: VVSvb312fowLDux4Tfwcgk9cnqb

📷 图片描述: 图片展示的是内存火焰图查看调用栈界面。上方有”Chart Statistics""Sample table""Flamegraph""Function”四个选项卡,当前选中”Sample table”。下方表格中,搜索栏输入”vulkanCreatePipe”后,显示了相关函数信息,如”vulkanCreatePipe”函数在”/vendor/lib64/hw/vulkan.adreno.so”库中,其”Total”占比2.06%,“Self”占比0.00%,“Samples”为0,对应线程ID为18685,函数名为”vglinternal::vkCreatePipelineCache(VkDevice_T*, VkPipelineCacheCreateInfo const*, VkAllocationCallbacks const*, VkPipelineCache_T***)“。该图与上下文介绍的内存火焰图查看调用栈内容相关。(token: CV5NbUFhpoblObxlKjlc66nFnAe

📷 图片描述: 图片展示的是内存火焰图分析界面,上方显示事件类型为”screen_mmap_page_alloc”,进程为19855(com.android.systemui),库为”vendor/lib64/libandroid.so”,函数为”mmap”。下方是火焰图,以不同颜色深浅表示不同函数的内存分配情况,红色最深,黄色最浅。图中还列出了函数名称及对应的内存分配函数,如”mmap”对应”mmap”等。该图是通过mem use工具hook抓取内存信息数据转成的火焰图,用于分析内存占用情况。(token: V0gdb7zV6oG2WVxgHcnclgX7nTc

火焰图diff对比

fire_html中的两个json文件,是基于火焰图的base数据做了格式化,前端工具解析该json文件

📷 图片描述: 图片展示了电脑文件夹中的内容,红色框突出显示了”simpleperf_html”文件夹。该文件夹下有多个文件,其中”p1_daily_iter1.json”和”p1_patch_iter3.json”被红色框标注,表明它们是与内存占用分析相关的JSON源文件。这些文件与文档中介绍的通过simpleperf抓取内存参数解析结果的内容相关,是前端工具解析的基于火焰图的base数据格式化后的文件。(token: Bgc7bgNaVoJrk6xWhbBcZCVLnRf

📷 图片描述: 图片展示了在文件夹中打开的”systemui_rss_values_systemui_traces_SM8850_vs_SM8750_vs_fake1_vs_fake2_native”文件夹内容。其中,“memuse_report_SM8850_iter1.html”和”memuse_report_SM8750_iter1.html”是html文件,分别对应SM8850和SM8750的内存占用情况;“memuse_report_SM8850_iter1.json”和”memuse_report_SM8750_iter1.json”是json源文件。图片与上下文关系为,上下文提到对比火焰图需通过网址打开,此图展示了html和json文件,是对比火焰图所需数据文件的存储示例。(token: S5Yobes8zoP9NFxHNxucZe2anrw

对比火焰图通过该网址打开:https://test.loadterminator.mioffice.cn/#/flamegraph/demo

📷 图片描述: 图片展示的是火焰图函数对比分析Demo界面,左侧为文件目录,右侧是文件列表。红色箭头指向”memuse_report_systemic_traces_SMB890_len1.json”文件,该文件被选中。界面右上角有”选择JSON文件”按钮,用于选择对比文件。该图片与文档中”火焰图diff对比”部分内容相关,说明了在前端工具解析的json文件基础上,通过网址打开对比火焰图的操作,直观呈现了对比文件的选择位置。(token: IwEhb3mINowBJzxetQOcsV3hnTg

📷 图片描述: 图片展示的是火焰图函数对比分析Demo界面。左侧为基准文件区域,有”选择JSON文件”按钮,下方显示基准文件为”memuse_report_systemui_traces_SM8850_iter1.json”,还有”开始分析""查看基准设备火焰图""查看对比设备火焰图”按钮。右侧为对比文件区域,同样有”选择JSON文件”按钮,下方显示对比文件为”memuse_report_SMB750_iter1.json”。该图片与文档中火焰图函数对比分析内容相关,用于说明火焰图对比分析时选择基准和对比文件的操作界面。(token: S8hZbABpDolpipxa02zc310NnQf

📷 图片描述: 图片展示的是火焰图函数对比分析Demo界面。左侧为基线文件,可选择JSON文件,当前选中p1_daily_test1.json;右侧为对比文件,同样可选择JSON文件,当前选中vivo_iter1.json。下方是函数名称列表,红色框突出显示了”mashcat_wm_page_alloc”函数。该图片与文档中”火焰图diff对比”内容相关,用于展示基于火焰图的base数据格式化后,前端工具解析的json文件在对比分析中的呈现形式。(token: FMNCbx72doY7xJxLBIlcaPSVnVg

📷 图片描述: 图片展示了内存火焰图对比界面,上方为base火焰图,下方为diff火焰图。base火焰图中,内存分配函数”kmem:mm_page_alloc”以紫色突出显示,其下有多个函数调用。diff火焰图中,同样以紫色突出显示”kmem:mm_page_alloc”,下方函数调用层级更多,颜色区分更细致。该图与文档中”火焰图diff对比”部分内容相关,用于直观呈现基于火焰图的base数据格式化后,前端工具解析的json文件对比情况。(token: Vbnvb4atsoK4cVxlZ4RcIT6FnQc

📷 图片描述: 图片展示了内存火焰图的两个关键部分。左侧是Cell Graph调用树图,呈现了内存分配的调用链路,绿色部分代表内存分配,红色部分代表内存释放,可看到如malloc等函数的调用情况。右侧是Caller Graph调用头链图,展示了函数调用的层级关系,红色线条代表函数调用,绿色线条代表函数被调用,可看到malloc、free等函数的调用层级。该图与上下文介绍的内存火焰图查看调用栈内容相关,用于辅助分析内存占用问题。(token: PAgdbDHbAowZYyxm2nzcnZtZnsg

分析案例

相关文档:内存工具-内存占用分析Systemui 开机native内存占用分析