背景与目标

目标:Pss 降低 200MB

测试场景:开机内存

机型对比:小米P1 vs 荣耀Magic8pro

内存差距:166M(166459KB)

内存细分

文件页(GAP = 189MB

匿名页-Native(GAP = 29MB

匿名页-Java(存量Java堆GAP值:8MB

Top Native MemFun. 一览(按竞品diff值降序)

[嵌入电子表格 Ai1ysVXKBhW6ZrtaeQ3cvZSUnOf]

函数级拆解

更多的 ShaderCache

qglinternal::vkCreatePipelineCache (diff = 11.76MB)

android::BlobCache::set (diff = 8.15MB)

android::BlobCache::Blob::Blob (diff = 1.98MB)

差距总计:21.89 MB

原因分析:

这3个是 Shader Cache相关,根本原因是小米SystemUI中使用了布局层级更为复杂的圆角嵌套效果,导致 ClipStack 更深,Shader组合效果(级联)更多,进而产生更多的 ShaderCache。

优化方案:

目前有一版相关的针对性优化方案正在跟进中,预计优化70%80% (**1619MB**) ---责任人 @王月

更多的 Bitmap 创建

android::Bitmap::allocateHeapBitmap

小米

VIVO:

荣耀:

位图数量差距+67 (VIVO) / +233 (荣耀)

位图内存差距:+10.7 MB (VIVO) / +5.6 MB (荣耀)

Top 10 位图列举:

  1. 通知 icon大图 1, 492KB (通知线程,*2张

业务侧入口函数:

com.android.systemui.statusbar.notification.row.NotificationRowContentBinderInjector$Companion.initAppInfo

  1. 通知 icon大图2,492KB (*2张)

业务侧入口函数:

com.android.systemui.statusbar.notification.stack.NotificationChildrenContainerInjectorImpl#updateMiuiHeader

  1. 锁屏大图,367KB

业务侧入口函数:

com.miui.keyguard.biometrics.fod.MiuiGxzwQuickOpenView.

  1. 锁屏大图,277KB

业务侧入口函数:

com.android.keyguard.blueprint.KeyguardPanelViewSection.addViews

  1. 通知大图,274KB

业务侧入口函数:

com.android.systemui.shade.NotificationDismissViewController.

  1. 通知图标,219KB(通知线程)

业务侧入口函数:

com.android.systemui.statusbar.notification.row.NotificationRowContentBinderInjectorImpl#handleAppIcon

  1. 通知大图,219KB

业务侧入口函数:

com.android.systemui.statusbar.notification.row.NotificationContentView#onMeasure

  1. 通知大图,219KB

业务侧入口函数:

com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer#onMeasure

  1. 锁屏大图,219KB (*5张)

业务侧入口函数:

com.android.systemui.statusbar.notification.policy.KeyguardNotificationController$1.handleMessage

  1. 通知大图,219KB (*4张)

业务侧入口函数:

com.android.systemui.statusbar.notification.utils.NotifImageUtil#getCustomAppIcon

  1. 通知大图,219KB

业务侧入口函数:

com.android.systemui.statusbar.notification.utils.NotifImageUtil#getCustomAppIcon

  1. 通知小图,161KB (多张)

业务侧入口函数:

com.android.systemui.statusbar.notification.utils.NotifImageUtil#getSmallIcon

优化方案:

  1. 非立即显示的Bitmap,考虑 lazy load 懒加载方式来创建
  2. 静态图片、Icon图标类图片,考虑设计上降低分辨率规格

更多的 RenderNode 创建

android::uirenderer::RenderNode::RenderNode (diff = 2.02MB)

差距总计:2.0 MB

原因分析:

由于dagger框架的使用 + Speed模式,引起几乎全量(90+%,根据dex文件数据访问火焰图)的预加载方案,小米SystemUI会比VIVO在开机启动场景下,创建并并缓存更多的View对象,涉及: 小窗、通知、锁屏、状态栏、控制中心等各模块。

更多的 文字绘制

GrDrawOpAtlas::addToAtlas (diff = 0.77 MB

SkArenaAlloc::ensureSpace (diff = 1.43 MB

差距总计:2.2 MB

canvas.dawText \ canvas.drawTextRun \ canvas.drawTextOnPath 等文字绘制API 调用触发。

SkArenaAlloc, 是Skia 中的一个 arena / bump-pointer 内存分配器,用于存储 绘制过程中的临时对象

原因分析:

View加载与预加载过程中,小米比VIVO触发了更多次的文字绘制,上层代码表现为更多的TextView渲染。

Miui-SmoothCorner 的创建

android::uirenderer::skiapipeline::SmoothCorner::SmoothCorner() (diff = 700KB)

SystemUI 进程中渲染线程 RenderThread 在初始化启动的时候,发现比VIVO多一次 700KB 的大内存分配:为创建**SmoothCorner(MIUI圆角效果)**引入的相关内存,定位到源码如下:

https://source-w.dun.mi.com/opengrok-w/xref/master-25q2-qcom-xiaomi/frameworks/base/libs/hwui/renderthread/RenderThread.cpp#303

责任人 @刘修全

原因分析:

SmoothCorner是美学需求驱动做的平滑圆角,在系统内的圆角矩形中大范围使用。关闭后则systemui 布局中无平滑圆角,体验上会有退坡。

更多的 VectorDrawable 使用

android::uirenderer::VectorDrawable::Path::Path (diff = 758KB

示例1:

miui.systemui.controlcenter.panel.secondary.media.MediaPanelDelegate.initView

示例2:

com.android.systemui.miui.volume.VolumeColumn.updateIcon

示例3:

com.android.systemui.statusbar.StatusBarIconView.getIcon

原因分析

小米的 SystemUI 中部分UI布局使用了SVG,包括控制中心媒体栏、音量条、状态栏图标等。为了启动速度优化,进行了UI的预加载处理,例如控制中心。因此在开机启动场景下,部分View,即使没有显示出来,也会提前创建(Inflate)。反观竞品,UI布局中未使用任何的 VectorDrawable。

MiuiSystemUI中 控制中心 预加载相关 commit:

https://gerrit.pt.mioffice.cn/c/platform/packages/apps/MiuiSystemUIPlugin/+/6407523