性能优化-内存
Shallow Size
对象自身占用的内存大小,不包括它引用的对象
Retained Size
当前对象大小+当前对象可直接或间接引用到的对象的大小总和
Bitmap内存在native中,不影响java虚拟机内存上限,android 8.0之后才在native中的,测试系统api 34模拟器中,循环调用BitmapFactory.decodeResource创建bitmap只是native内存增长
code,stack,java变化很小,只有native和other 的内存一直在增长
每次创建bitmap对cpu都有一定的消耗
java对象内存很小
native内存已经1.3G多了,java 虚拟机内存的内存也没有过多变化
被强制杀掉进程了
陆续杀了一些其他进程,接着是demo进程
系统终止进程 “com.example.jnidemo” 来缓解内存和交换空间的压力,java虚拟机没有达到上限,但native 尝试分配太多内存也会被杀掉,可以主动释放些内存,实际中除了泄露应该用不这么多内存的
换个真手机,1200块的普通oppo手机,总内存达到8.8G,natvie 3.7G,others 5G,才被杀掉
通过bitmap创建申请了几乎8g的native 内存,但java 虚拟机内存一点变化都没有
RGB_565格式设置不一定生效,系统会查看当前图片是否有透明通道,没有透明通道的是你才会生效,如下面代码,只有把图片去掉图透明通道,才是每像素4字节,否则都是8字节每像素
1 | val optionsNew = BitmapFactory.Options() optionsNew.inPreferredConfig = android.graphics.Bitmap.Config.RGB_565 |
Bitmap.createBitmap 也是放native中
Bitmap对象,java层的Bitmap对象很小,其中通过一个mNativePtr native bitmap 的指针,关联native分配的内存
1 | Bitmap.createBitmap(1024,1024,Bitmap.Config.ARGB_8888) |
内存分析工具及方式:
Profiler
可以直观的看到实时的各类型内存,还可以捕获堆转储,只适合线下
内存计数中的类别:
Java:从 Java 或 Kotlin 代码分配的对象的内存。
Native:从 C 或 C++ 代码分配的对象的内存。
即使您的应用中不使用 C++,您也可能会看到此处使用了一些原生内存,因为即使您编写的代码采用 Java 或 Kotlin 语言,Android 框架仍使用原生内存代表您处理各种任务,如处理图像资源和其他图形。
Graphics:图形缓冲区队列为向屏幕显示像素(包括 GL 表面、GL 纹理等等)所使用的内存。(请注意,这是与 CPU 共享的内存,不是 GPU 专用内存。)
Stack:您的应用中的原生堆栈和 Java 堆栈使用的内存。这通常与您的应用运行多少线程有关。
Code:您的应用用于处理代码和资源(如 dex 字节码、经过优化或编译的 dex 代码、.so 库和字体)的内存。
Others:您的应用使用的系统不确定如何分类的内存。
Allocated:您的应用分配的 Java/Kotlin 对象数。此数字没有计入 C 或 C++ 中分配的对象。
dump简易信息
1 | adb shell dumpsys meminfo com.example.jnidemo |
看到大致内存信息,像code,native heap dex so等
内存统计,Activity数量和view的数量
看更详细的信息,这个需要debug包
1 | adb shell run-as com.example.jnidemo cat /proc/18047/maps |
可以用个python脚本把上面的内存地址计算成大小,做个排序
用命令dump内存堆
dump 内存堆到指定目录
1 | adb shell am dumpheap $pid /data/local/tmp/xx.hprof |
还需要调用 转成能够分析的hprof
1 | hprof-conv -z xx.hprof out.hprof |
可以写成一个脚本把上面两步骤写在一起,dump出来的会在当前目录的heap目录里面
1 | rm -rf heap |
第三方性能分析工具:
PerfDog性能狗 开始收费了
火山引擎性能分析工作台目前已找不到下载入口了,估计是开始针对性能收费了
自行开发个,思路利用adb + app_process + socket 提权获取信息开发个桌面性能分析工具
Mat工具
Leak Suspects:直击引用链条上占用内存较多的可疑对象,可解决一些基础问题,但复杂的问题往往帮助有限。
Top Consumers:展现哪些类、哪些 class loader、哪些 package 占用最高比例的内存。
Path To GC Roots:提供任一对象到GC Root的链路详情,帮助了解不能被 GC 回收的原因。在排除弱引用
Dump 前主动手动执行一次 FULL GC,profiler 工具可以触发 ,去除无效对象进一步减少 dump 堆转储及建立索引的时间
线下内存检测
LeakCanary
LeakCanary1.0版本的HAHA解析引擎,解析速度很慢,解析过程很容易oom
KOOM基于Shark引擎进行解析
LeakCanary2.0版本使用Shark新版解析引擎
线下大图检测
AMS插桩修改字节码,修改imageview的父类获得view的高宽和bitmap的高宽
线上检测
达到阀值,触阀dump,子线程dump或者,另起进程dump内存堆,然后通过mat软件分析分析
裁剪Hprof文件,以降低后台存储Hprof的开销
快手的Koom
大量OOM分析:时候通过shark或者haha库分析捞上来dump堆,把数据入库,统计聚合分析
主动释放内存
定期主动释放部分内存
特殊场景下,释放内存,如长时间在后台
收到onTrimMemory信号主动释放内存
达到阀值释放部内存
android虚拟机内存使用计算
1 | Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); |
StrictMode
检测出一些不合理的代码块。
StrictMode分为线程策略(ThreadPolicy)和虚拟机策略(VmPolicy)
检测对IO、网络、数据库等相关操,主线程耗时操作,通过其相应崩溃日志定位问题