当前位置:首页>安卓APP>会议戮:应用内存超标,安卓和3D谁的锅?

会议戮:应用内存超标,安卓和3D谁的锅?

  • 2026-10-13 14:51:48
会议戮:应用内存超标,安卓和3D谁的锅?

剧目

议题
座椅进程内存超标(1.2GB),3D的还是安卓的?
背景
性能测试发现座椅进程内存占用超标,测试提bug,安卓工程师分析认为是3D超的,把bug单转给了3D。
参与部门
软件开发-3D组、软件开发-安卓组

本故事纯属虚构,仅用来表达业务思考。

角色表

  • 金平 | 3D开发

"你这些什么Heap什么Dump的,我哪看得懂?"

  • 张明哲 | 安卓工程师

"不解耦的下场就是要花时间沟通这种你的、我的、还是他的问题"


对话

张明哲(安卓) :金平,这个内存占用超标的bug我转给你了你看下,紧急bug,今日必解。

金平(3D) :我看到了这个bug,但是我有点看不懂啊,你说的Heap是啥?

张明哲(安卓) :那我先说下,情况是座椅调节界面在进入退出三次后,进程总内存占用达到了1.2GB,比标准值高出500MB。我在Android Studio抓了Heap Dump,你看这个Android Studio的Profiler截图(投屏显示)。Heap Analyzer 中前面几个大的:

  1. byte[]加起来大概180MB
  2. android.graphics.Bitmap的实例数不多,但Native Size这一列加起来将近220MB
  3. 再往下还有一堆跟图片解码相关的临时缓冲。

这些加起来四五百兆,跟你们每次打开界面涨的那一截对得上。

金平(3D) :你说的这些byte[]和Bitmap是我申请的?我Unity这边加载资源用的是引擎自己的API,比如AssetBundle.LoadAssetAsync,走的是引擎自己的资源管线,我代码里根本没有什么android.graphics.Bitmap,也没有BitmapFactory啊。

有点懵,这些不会真是Unity申请的内存吧...

张明哲(安卓) :对象名字是Java的,不代表跟你们无关。你看这个引用链,大块byte[]最终能追到UnityPlayerActivity附近;Bitmap的Native Size又这么大,我安卓这边的素材都不会这么大的,Unity里加载的贴图更有可能吧?

金平(3D) :引用追到UnityPlayerActivity,那也不能说明它是我Unity业务逻辑的Texture吧。再说了,我们Unity的Texture2D、Mesh这些在引擎Native堆和GPU侧,根本不应该会以Texture2D这种类名出现在你这个Heap Analyzer列表里。你拿Java Heap Dump的结果,直接认作Unity的,可能不对哦。

你拿Java的分析工具看Unity的纹理内存,这是不是有点牛头不对马嘴?

张明哲(安卓) :我试过,我去掉 3D 的 Library,然后打包后本地台架测过了,内存是正常的。但是加了你们的 Library 就复现了,切换几次,进程总内存就涨一截。这总归是你们3D这边有什么问题吧。

哪有那么多时间和你一起深入到你自己那块去分析。我就用这个去掉 3D 做对比的招儿,你总没话说吧。

金平(3D) :不可能啊,每次切换,我这里又不会重复加载什么资源,怎么可能打开一次就涨一截内存呢?!你说的“每次涨一截”,涨的是哪一块内存?

张明哲(安卓) :你看这个Allocation Call Stack。这条大块分配落在android.graphics.Bitmap.nativeCreate,上层是BitmapFactory.decodeByteArray,再往上是宿主侧的一张图解码路径,最后间接关联到你们Unity界面打开时的业务回调。

金平(3D) :这条是Android Bitmap解码路径,不是Unity的AssetBundle或是纹理的什么路径。Unity从AssetBundle加载纹理,走的是引擎Native解码和Graphics API,正常不会经过BitmapFactory.decodeByteArray。你这条链路更像是App主线程自己在解码Bitmap,跟我Prefab加载不是同一条管线,你是不是在接我这块的时候,加了什么Bitmap的东西啊?

我没用Bitmap啊,这是哪来的?

张明哲(安卓) :呃……我之前是有做了一个对 3D 的截图的机制。那个时候,因为热启的时候3D座椅画面老是慢半拍恢复,我只能拿截图挡一下,去解那些“闪一下”的问题。Heap Dump里的这一两百兆可能是我这里的问题,我会后再去看看。但是还有呢,还有两三百兆的增量哪来的呢?

我之前以为Native Heap就代表所有Native内存,看来不全是。

好像确实截图有点问题,不全是Unity的,这里怕是有两个问题!

金平(3D) :把完整的dumpsys meminfo 秀出来看一下呢。

难不成 3D 这里是大头所在?

张明哲(安卓) :行,adb shell dumpsys meminfo <pid>

Applications Memory Usage (in Kilobytes):** MEMINFO in pid 28453 [com.example.unityapp] **                   Pss      Private   Private   SwapPss                 Total      Dirty     Clean     Dirty  Native Heap   280000     275000       5000       0  Dalvik Heap    45000      44000       1000       0  Dalvik Other    5000       4800       200        0        Stack      512        512         0        0       Ashmem        2          0         2        0    Gfx dev       8500       8500         0        0   Other dev       200        120        80        0     .so mmap    95000       2000     65000        0     .jar mmap     800          0       400        0     .apk mmap    1200          0       600        0     .ttf mmap     300          0       200        0     .dex mmap    3000       2800       200        0     .oat mmap    1500          0       800        0     .art mmap    2000       1500       500        0    Other mmap     500         50       450        0   EGL mtrack   420000     420000         0        0    GL mtrack   380000     380000         0        0    Unknown      30000      29800       200        0       TOTAL  1273514    1171082     74232        0  App Summary                        Pss(KB)                         ------           Java Heap:    45000         Native Heap:   280000                Code:    98000               Stack:      512            Graphics:   808500       Private Other:    40000              System:     9502             TOTAL:  1273514  TOTAL PSS

金平(3D) :Graphics应该就是3D渲染相关内存的大头。Unity的纹理、Mesh的GPU缓冲、RenderTexture主要在这里。你之前的Heap Dump 肯定就不是了。

CPU侧:

  • Native Heap(~280MB):malloc/new出来的C/C++堆,含Unity引擎运行时、IL2CPP、部分资源解码缓冲等
  • Dalvik/Java Heap(~45MB):宿主Activity、View、以及你Heap Dump里能直接点到的Java对象
  • .so mmap(~95MB):libunity.so、libil2cpp.so等动态库映射

Graphics侧(合计约808MB):

  • GL mtrack(~380MB):驱动上报的GL内存,主要是纹理、GL命令缓冲、部分驱动固定开销
  • EGL mtrack(~420MB):主要是Surface,EGL分配的buffer

Graphics 这 800MB 里,有多少是座椅界面、有多少是别的界面残留,我得靠Unity Memory Profiler和你的meminfo对比。如果有没卸干净的GPU资源也有可能造成这种现象。

张明哲(安卓) :行吧,那你查你的,我去查我的。

金平(3D) :嗯,切换后如果 Graphics 占用和 Unity 快照都能回落,那问题就不大,就不是内存泄漏,只是需要做内存占用优化,我之后会把结论更新到bug单中的。

哎,逃过一劫。


结语

Unity 以 Library 嵌进 Android 时,它会有:Java 堆(Heap Dump 主要在此)、Native Heap(引擎/运行时及各类 native 分配)、Graphics(GL/EGL mtrack 等图形相关总量)。

Heap Dump 看不出 Unity 纹理/Mesh 的 GPU 明细;内存资源明细还是需要看 Unity Memory Profiler。

还是服务化渲染好,大家不共进程,能少处理些掰不清楚的问题。

对于加了3D就怎么怎么,不加就没问题的说法,要意识到,这也可能是3D的运行,让宿主App的错误逻辑或是系统驱动的潜在问题显现出来了。

最新文章

随机文章