性能优化1 - 内存抖动

  • 什么是内存抖动
  • 内存抖动的影响
  • 引起内存抖动的原因
  • 如何发现内存抖动
  • 内存抖动常见的解决方式

Android 是基于 Java ,不管是刚刚接触 Android 的新手,还是混迹在开发前线的老手,都知道在 Android上面的开发,不用管内存的回收,需要对象的时候 new 出来就好了,其余的 GC 会帮助我们,但是 GC 也不是万能的,GC 机制帮助我们的同时,也会限制我们,俗话说有得有失嘛。今天来看一下由于这种机制给我们带来的第一个坑,内存抖动。

什么是内存抖动

内存回收是指在程序需要对象的时候,在堆当中分配出来一块空间,使用完毕以后,由 GC 帮我们清理掉这片内存空间。如果频繁的一直持续上述操作,就会引起内存抖动。也就是有源源不断的对象被创建,同时又有源源不断的对象被回收。

内存抖动的影响

  • 导致程序卡顿
  • 导致程序内存溢出

出现上述情况的内存抖动,会对程序造成什么影响呢,首先我们知道 GC 回收的时候也是需要消耗资源的,比如 GC 回收的时候会停止掉所有的线程,如果触发一次 GC 就停止一次,那如果多次频繁的触发 GC 线程也会一卡一卡的,所以总的来说内存抖动可能会造成程序的卡顿。

如果发生频繁的 GC 会导致出现不连续的内存片无法进行分配,导致 OOM 内存溢出。

注意:Android 垃圾回收机制使用的是 CMS 垃圾回收器 (采用标记 - 清理算法)

引起内存抖动的原因

内存抖动出现原因主要是频繁在循环里创建对象,导致大量对象在短时间内被创建,由于新对象是要占用内存空间的而且是频繁,如果一次或者两次在循环里创建对象对内存影响不大,不会造成严重内存抖动这样可以接受也不可避免,频繁的话就很内存抖动很严重。

如何发现内存抖动

首先我们先来看一个简单的 Demo

我们知道 Java 当中的字符串对象是不可变的,如果累加的话。会将原来的 Copy 出来一份。然后进行累加成为新的字符串,原来的就会被回收掉,现在我们就利用这个特性来模拟一个简单的内存抖动现象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

public void onClick (View view) {
for (int i = 0; i < 1000; i++) {
String tempTestString = " ";
//拼接打印
for (int j = 0; j < 200; j++) {
tempTestString += " ++";
tempTestString += " --";
}
}
}
}

这样必然会出现内存抖动,我们通过 AS 自带的工具观察一下内存的使用情况,如下所示:

内存分析图

有小白色的垃圾桶,说明触发了 GC ,有一个代表出发了一次 GC ,上图有多个,然后我们选定一个时刻,仔细的看一下对象,例如下图

内存抖动分析图

可以看到对象最多便是char数组,和 String 类型,然后点击 String,随便选取一个实例,查看他的堆栈,双击 便可以定位到我们的代码当中,然后结合详细的代码,进行分析,便可以规避上述的问题。

内存抖动分析图

内存泄漏常见的解决方式

  • 尽量避免在循环体内创建对象,应该把对象创建移到循环体外。
  • 注意自定义View的onDraw()方法会被频繁调用,所以在这里面不应该频繁的创建对象。
  • 当需要大量使用Bitmap的时候,试着把它们缓存在数组中实现复用。
  • 对于能够复用的对象,同理可以使用对象池将它们缓存起来。

参考文献:

https://www.cnblogs.com/xgjblog/p/9042458.html
https://blog.csdn.net/wanghao200906/article/details/79311288
https://blog.csdn.net/nicolelili1/article/details/89219191
https://blog.csdn.net/qq_31370269/article/details/52818277
https://blog.csdn.net/wanghao200906/article/details/79311288
https://www.youtube.com/watch?v=McAvq5SkeTk