正文
}
func bubbleSort() {
var x, y, z, passes, key : Int
for (x = 0; x
passes = (numberList.count - 1) - x;
for (y = 0; y
key = numberList[y]
if (key > numberList[y + 1]) {
z = numberList[y + 1]
numberList[y + 1] = key
numberList[y] = z
}
}
}
}
这段代码主要是对数组的添加和删除,两种方法执行起来耗时不多,但后台发生的系统动作却多得让人眼晕。
可以发现,代码用到了很多间接依赖,这些都是支撑代码运行的系统库文件。因为处理大数据集比较消耗系统资源,所以要尽可能地把繁重的操作放到后台去做,上面的代码就走的后台线程。在上图的 Call Tree 中可以看到,被调用的堆栈名是 dispatchworkerthread3。如果把它放到主线程去执行,程序肯定会挂起。不信你注释掉 dispatch_async 调用看一下。
再来个图片加载的例子。
这儿有三种图片加载方法:
-
loadSlowImage1:从指定 URL 下载一张图片(加载速度慢)
-
loadImage2:从本地资源库加载一张图片(注意:没用系统缓存)
-
loadFastImage3:从系统缓存中加载一张图片(加载速度快)
看看Time Profiler算出的结果是不是跟预想的一样。
进入演示应用第二项「Time Profiler: Our Methods」,点击「Reload」十次来重复加载图片,这样能产生足够的数据来分析。然后在 Time Profiler 图表中通过拖拉鼠标选中要放大查看的区域,从 Call Tree 中双击调用了 .reload 方法那一行(上图中加亮选中那一行),就会跳转到对应的代码行,所用时间也标注出来了。
看到谁最花时间了吧。虽然代码没什么可优化的地方,但大家应该认识到缓存能发挥的作用。所以即使有时还得调用 loadSlowImage,多数情况下把图片缓存下来,还是能省些资源占用。
Call Tree 的选项设置。
这些选项默认是不选的,但把它们勾选上可以帮你更快定位到关键的代码上,往往这也是问题的源头。
-
Separate by Thread:按线程分开做分析,这样更容易揪出那些吃资源的问题线程。特别是对于主线程,它要处理和渲染所有的接口数据,一旦受到阻塞,程序必然卡顿或停止响应。