本篇的主题叫做内存抖动与计算性能优化,相信很多人都不清楚什么是内存抖动和计算性能优化。
那接下来就开始介绍:
什么是内存抖动?
之前我们解决了哪些讨厌的泄露,现在遇到了更大的问题,内存抖动。要知道,堆内存都有一定的大小,能容纳的数据是有限制的,当Java堆的大小太大时,垃圾收集会启动停止堆中不再应用的对象,来释放内存。现在,内存抖动这个术语可用于描述在极短时间内分配给对象的过程。例如,当你在循环语句中配置一系列临时对象,或者在绘图功能中配置大量对象时,这相当于内循环,当屏幕需要重新绘制或出现动画时,你需要一帧帧使用这些功能,不过它会迅速增加你的堆的压力。这两种情况下,我们都制定了解决方案,可在短时间内创造大量的对象。根据创造的对象的量,或者每个对象的大小,你可能很快就消耗掉所有剩余内存,导致垃圾收集强行开启。随着它们的开启运行,会消耗更多宝贵的帧时间,所以,高性能的应用很有必要,你需要鉴别并从内循环里,取消会被重复执行的代码配置。为了更好的寻找到这些代码配置,Android Studio为此特别打造了一个方便的工具。
内存抖动
使用Allocation Tracker:
现在看一下你的应用内存分配图,这能有效的获悉大部分数据到底用在哪里,以及正在分配哪种类型的数据,这能
帮你找到现有的不必要分配的数据。可惜Heap Viewer不能显示你的数据具体分配在代码的何处,为此,我们需要一个
叫做分配追踪器的工具。和以前一样,我们打开Android Studio Device Monitor,在前台载入Sunshine,打开DDMS
视图点击startallocation tracking按钮,然后使用应用,隔一段时间在点击stop allocation tracking按钮。停止之后在
DDMS出现了一个列表,这个列表显示了你在使用应用期间,所有的分配情况,这里的每一行都代表不同的分配,
allocation order这一栏会提示你,分配进行的具体时间,分配类别这一栏显示了分配数据的类型,以及大小,还有其
他信息来告诉你哪个线程具体决定了这一分配。最后,分配站这一栏告诉你代码的哪一个功能实际分配了内存。比如
,我们选择整型,测试的值决定了这个整型的分配,如果你点击一个分配,你可以看见完整的调用堆栈。这个表格包
含大量信息!通过Allocation Tracker能定位大致的情况:
接着可以通过TraceView来确定详细的问题所在:
通过跟踪显示来剖析这个活动,打开traceview的面板,注意短时间内发生的频繁的垃圾收集活动,可能会伤害到
应用的性能。记住,我们还可以采集这个内存监控器图像,这个截屏展示了内存抖动是怎样通过Memory Monitor清晰
显示的。(具体使用参考之前的博文):
上图的详细列表那些花花绿绿的又有一大片黑色的部分就是导致内存抖动的原因,之所以是花花绿绿的是因为在那段
时间内不断消耗了内存,不断的new对象,短时间内发生了大量的内存分配导致了UI卡顿。到这里我们就可以点击黑
色部分其中一段就可以定位到具体的代码处,进而解决问题。
上面介绍完内存抖动,接下来我们继续讲解计算性能优化:
这里我们先来举一个例子: 斐波那契数列相信大家都听过(不清楚的自行Google)
我们可以通过Android Studio的Android Monitor去监听:
发现此时没有发生内存抖动,但是发现Cpu的占用比增大,以至于程序发生crash
接着我们就可以通过TraceView来确定发生的具体位置:
在下面的活动上运行TraceView,当我按下这个computeFibonacci函数,将会剖析这个函数。这是Traceview的输出,
这是运行Traceview时看到的输出,你应该看到一些类似的内容,请注意这个大的粉色区域,这很糟,基本上,这表示
有些函数在我们的主线程上占用大量的CPU时间。如果你按照独占CPU时间排序或者将鼠标悬停在这个粉色区域。你
会发现computeFibonacci方法,它来自于我们的缓存活动,是占用CPU资源最多的函数,我们需要解决这个问题。
这里为什么不是花花绿绿的呢?因为这里调用的是同一个方法,这个方法很消耗时间。
解决问题:
这是我们原先了解的递归算法,虽然能很好的解决很多问题但是对于Android手机来说,会导致占用
CPU时间过长,进而导致UI卡顿。
这里我们可以利用中间变量缓存的方法来优化代码:
//优化后的斐波那契数列的非递归算法 caching缓存+批处理思想
public int computeFibonacci(int positionInFibSequence) {
int prev = 0;
int current = 1;
int newValue;
for (int i=1; i<positionInFibSequence; i++) {
newValue = current + prev;
prev = current;
current = newValue;
}
return current;
}
这样子就可以减少CPU占用的时间。
具体为什么内存抖动和耗时计算会导致UI卡顿,下一篇博文继续介绍。