聊聊 iOS 5 和 iOS 6 在HTML5 canvas渲染上的差异
我录制了一段iphone4s下ios5和ios6的canvas性能对比视频http://t.cn/zlvnKZk通过这个视频我们可以发现很多有趣的事情.简单来说iOS6的特点就是:以退为进,为了更好的体验,而减速!!!!未来A6芯片+iOS6下的HTML5体验一定会很赞!
视频地址:http://v.youku.com/v_show/id_XNDQ5OTY1ODk2.html
javaeye怎么不能潜入flash视频了?
下面说说我的看法.
视频中白色的是iOS5,黑色的是iOS6gm版(相当于正式版).
首先对这个视频里的测试页面做一下说明.
测试页面地址:http://tryhtml5.sinaapp.com/op/logo.html
测试用例的特性:
基于canvas,画面背景是一张彩虹色的大图,
前景是180个(6种)logo图片,图片大小在500*500左右,渲染时,缩小+移动+旋转
logo在移动时采用的是固定步长.也就是每次loop时,logo移动的像素数量是固定的,与每次loop的间隔时间无关.(这点很重要)
在视频中,我们可以发现如下特点:
iOS5里logo移动的快,但是不顺畅,一跳一跳一卡一卡的.
iOS6里的则相反,logo移动的速度相对慢一些,但是更顺滑.
logo移动快慢大家可以通过计时(某一行logo移动一个来回需要的时间),或者是对比着看,同一行logo,在iOS5上会逐渐拉开iOS6上的logo.
=====================
在谈论iOS6带来的这种"改变"的之前,先来说一说在canvas渲染时,整个浏览器的一个内部流程.
实现一个canvas动画在完美情况下(60FPS),一秒钟内,浏览器是做了如下事情
1运行js代码,更新canvas的imageData数据
2根据canvas里最新的imageData去渲染画面
31到2重复60次
完美情况下上面的工作可以顺利的进行.浏览器的js线程和ui渲染线程是互斥的,同一时刻只能做一件事情.
那么当渲染画面成为瓶颈的时候,一切就不是如此了.
一种处理方案是:等待每一次渲染的完成再进行下一次工作.
这样在一秒内,js执行的次数==渲染的次数<60
另一种方案是:系统有选择的放弃掉【若干渲染】,从而【保证js】的执行次数受到尽可能小的影响.
那么在一秒内,渲染的次数<js执行的次数<60
通常情况下渲染性能无论多高,都会低于js执行的性能的,所以当渲染跟不上计算时,通常会选择第二种方案.
=====================
下面我们来根据视频猜测一下----真的只是猜,真实原因只有safari工程师自己出来说才行,否则我只能猜,我知道这样是不严谨的,根据现象猜原因是错误的,但是,对不起,就让我错一次吧。
第二种方案中,最终效果的好坏,则取决于放弃【若干渲染】,里的若干到底是多少,以及【保证js】运行要保证到什么程度,系统需要在这两方面做出权衡。
但是一个简单的原则就是:渲染能力越低,需要放弃的渲染越多,渲染能力越高,需要放弃的越少。
通过视频我们可以看出,
iOS5里为了保证js的运行,放弃掉了很多渲染,但是js执行的次数几乎没有受到影响。
而iOS6则大大减少了放弃掉的渲染(顺滑了很多),而同时,js的运行只受到了微小的影响(但还是受到了一些影响).
同时,提高渲染速度,适当降低js权重,这也使得用js记录FPS的方式比以前准确了很多.
但综合来看,iOS6的调整对整体的体验带来了巨大的提升,同时iOS6能够做出这种调整,很可能是因为渲染能力的提升使得它可以勇敢的选择放弃更少的渲染.
(如果iOS5里采用iOS6的策略,结果可能是双输:js次数得不到保证,渲染也得不到什么提升)
另,有朋友说iOS5里丢帧是bug(因为android里面有这个bug),但是我不同意这种观点,因为了解iOS5的朋友应该清楚,iOS5的canvas里已经引入了硬件加速,它的canvas性能和表现力在当时已经是逆天的了.这么优秀的平台不太可能有这么低级的bug.而且,如果是bug,它出现的频率和严重性也不应该有如此严重的人工干预的痕迹啊.
换句话说:"渲染压力不大时,完美渲染,渲染压力加大时,放弃掉一些渲染以保证程序的运行"这个怎么看都像是策略而不是bug啊.
===========
本文很多观点基于猜测,欢迎大家来拍砖!