Android开发经验谈Android开发Android技术知识

android性能优化-内存

2019-01-21  本文已影响14人  sunhapper

书籍推荐

市面上android性能优化的书籍不多
因为性能优化这块稍微深入一点,涉及知识的深度和广度就比较大了,而且性能优化依赖很多的平台相关的工具和分析技巧,导致通用性和实效性又不太高,所以以下书籍的内容也比较浅尝辄止

移动App性能评测与优化

Android移动性能实战

Android应用性能优化

内存性能分析及优化的意义

Overview of memory management
内存管理介绍

OOM

Low Memory Killer

GC

综上

关注并减少应用的内存消耗可以减少oom的概率,在内存紧张的场景下获得更好的用户体验,也可以增加应用的后台存活时间

工具介绍

调查 RAM 使用情况

dumpsys procstats

用来衡量一段时间内应用消耗内存的情况

(最小PSS-平均PSS-最大PSS/最小USS-平均USS-最大USS)


procstats.png

LeakCanary

检测内存泄漏的工具

MAT

比较常用的内存dump文件分析工具

使用方法

hprof-conv -z src dst //-z可以排除android框架创建的对象

使用场景

分析场景构建

性能测试的一些注意点

常见的性能测试方式

容易出现内存问题的场景

常见的内存问题

内存泄漏

内存泄漏产生的原因

一个对象的生命周期已经结束了,但是有其他对象持有了它的实例导致无法在GC时被回收,在Android中通常是Activity在finish之后依然有对象引用它导致内存泄漏

内存泄漏的常见场景

内存泄漏在分析工具上的表现

内存泄漏.png

每次activity的重建都会造成内存上升且gc不会使内存使用降低

内存泄漏的避免

内存抖动

内存抖动的原因

内存抖动一般是瞬间创建了大量对象,会在短时间内触发多次GC,产生卡顿

内存抖动的场景

内存抖动的在分析工具上的表现

内存抖动.jpg

制造了一个内存抖动的场景

 public void testThrashing(boolean needLog) {
        int dimension = 300;
        int[][] lotsOfInts = new int[dimension][dimension];
        Random randomGenerator = new Random();
        for (int i = 0; i < lotsOfInts.length; i++) {
            for (int j = 0; j < lotsOfInts[i].length; j++) {
                lotsOfInts[i][j] = randomGenerator.nextInt();
            }
        }
        //优化以前
        for (int i = 0; i < lotsOfInts.length; i++) {
            String rowAsStr = "";
            int[] sorted = getSorted(lotsOfInts[i]);
            for (int j = 0; j < lotsOfInts[i].length; j++) {
                rowAsStr += sorted[j];
                if (j < (lotsOfInts[i].length - 1)) {
                    rowAsStr += ", ";
                }
            }
            if (needLog) {
                Log.i(TAG, "Row " + i + ": " + rowAsStr);
            }
        }
    }

    public void optimizeThrashing() {
        int dimension = 300;
        int[][] lotsOfInts = new int[dimension][dimension];
        Random randomGenerator = new Random();
        for (int i = 0; i < lotsOfInts.length; i++) {
            for (int j = 0; j < lotsOfInts[i].length; j++) {
                lotsOfInts[i][j] = randomGenerator.nextInt();
            }
        }
        //优化以后
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < lotsOfInts.length; i++) {
            sb.delete(0, sb.length());
            int[] sorted = getSorted(lotsOfInts[i]);
            for (int j = 0; j < lotsOfInts[i].length; j++) {
                sb.append(sorted[j]);
                if (j < (lotsOfInts[i].length - 1)) {
                    sb.append(", ");
                }
            }
            Log.e(TAG, "Row " + i + ": " + sb);
        }

    }

解决方案

图片加载的内存占用

不同dpi文件夹对图片内存的影响

文件夹 对应dpi bitmap width height size 倍数
nodpi 1920 1080 8294400 1
xxxhdpi 640 1320 743 3923040 0.47
xxhdpi 480 1760 990 6969600 0.84
xhdpi 320 2640 1485 15681600 1.89
mdpi 160 5280 2970 62726400 7.56
图片加载.png

RGB565

除了图片资源的文件夹,加载图片时使用的色彩模式也影响了Bitmap大小。ARGB8888使用了32bit,所以一个像素需要4byte;RGB565使用了16bit,一个像素只需要2byte
但是因为RGB565少了alpha通道,对有透明度的图片显示有问题,而且显示效果上还是有些区别,所以并不建议修改这个属性,只是在对内存有严格要求的场景下可以作为特殊手段进行优化

ProGuard对内存的影响

压缩代码和资源

内存碎片

Overview of memory management 内存碎片

Davik的内存回收算法不能移动对象,所以会造成一个小对象占据整个内存页,产生内存碎片
而ART虚拟机的可以在GC时对内存空间进行整理,随着5.0以上系统的占有率逐渐提升,内存碎片造成的内存消耗可以不必过于关心

其他内存问题

Manage your app's memory

to be continue...

上一篇 下一篇

猜你喜欢

热点阅读