as3 弹性跑道模型
2005年,Ted Patrick发布了一篇伟大的文章《elastic racetrack》。它充当了我多年的参考资料,用于理解一帧内的代码的执行和渲染是如何平稳的处理的。等到了FlashPlayer9和AVM2的面世,我发现弹性跑道模型有了一些变化。此信息是基于我对FashPlayer内部事件和渲染的研究,但整个模型并没有被Adobe公司的工程师证实。
弹性跑到模型的基础没变:以一个具体的帧率运作,FlashPlayer会用帧的第一部分来执行代码,第二部分渲染显示对象。每个部分都能增加它的跑道,以容纳更多的指令处理和有效的延长帧的持续时间。
<ignore_js_op>
跟以前的模型相比,这两个部分有什么变化,它们在一帧内又是如何相处的?
AVM2被一种我称之为Marshal的东西控制着,Marshal负责为FlashPlayer提供时间片(一秒钟执行的次数)。首先要说明的是这些时间片与帧率不是同个东西,接着我们会看到FlashPlayer如何在帧率下综合处理这些时间片的。在MacOSX的火狐浏览器中运行一个Flex程序,Marshal每19-20毫秒的执行一个时间片,但据我观察以及Adobe员工的暗示,这个时间在不同的操作系统和不同的浏览器下是不同的。同时也取决于swf文件是如何编译的,可以看一下下面的注解。为了方便计算,我们以20毫秒执行一个时间片来进行假设。这意味着Marshal每秒钟尝试生成和执行不超过50片,然后它可能会根据代码的执行和渲染弹性的减少。每个时间片都可能按下列5个步骤顺序处理。
1 FlashPlayer事件分发—包括定时器,鼠标,ENTER_FRAME,URLLoader等分发的事件……
2 用户代码执行--监听第一步分发的事件的代码在这个阶段执行。
3 渲染事件被调度—当stage.invalidate()执行时,这个特殊的事件被调度。
4 最后用户代码被执行—监听第3步的代码在这时候被执行。
5 FlashPlayer重新渲染改变显示列表。
<ignore_js_op>
Marshal在脚本运行的时候反复的飞速执行这个20毫秒片。时间片内的脚本处理将产生两个主要跑道(代码处理与渲染),这两个跑道组成了1帧。用户动作和失效的动作放在代码跑道上,而渲染动作则放在渲染跑道上。主要注意的是,这些脚本只会Marshal分配的时间内执行。所以,如果你只是执行一个很短的操作,Marshal也会等待几毫秒再执行失效的动作和渲染动作。 观察哪些动作在执行,弹性跑道如何创建的最好方法是看这些时间片在5帧,25帧,50帧下的表现。 <ignore_js_op> 正如你所看到的,弹性跑道每帧执行不同的动作,而FlashPlayer会根据帧率综合而成不同的视觉图像。所以在帧率为5的时候,每帧处理10个用户动作,1个失效动作,1个渲染动作。在帧率为25的时候,每帧处理2个用户动作,1个失效动作,1个渲染动作。在50帧的时候,每帧处理1个用户动作,1个失效动作,1个渲染动作。必须注意的是,有些事件只在某些片可用。例如,Event.ENTER_FRAME事件只会在一帧的第一个片中被分发。 那么,这意味着什么呢?请往下看。 1 代码执行时间或渲染时间过长,弹性跑道会延长一个20毫秒片的时间。弹性跑道就会决定,特定的片和帧的持续时间会不会因此而延长。Marshal可能会丢弃一些片,以保持真实的帧率接近编译的帧率。 2 真实的帧率不会超过Marshal所决定的帧率。你可以设置帧率为120,但是FlashPlayer最多执行50片,最多渲染50次。(或多或少由系统配置决定)。 3 代码可以比设定的帧率执行的更频繁。如果帧率设为1,那么Timer或者鼠标的事件会出现在每一片中(一秒50片),但只会在最后一片中执行。此外,只要你愿意,你还能用updateAfterEvent()加快执行屏幕上的渲染,但只有在响应鼠标,Timer或者键盘事件的时候才能调用此方法。但在这种情况下,Marshal会认为1帧结束了,然后在下一片中开始新的1帧。。最后,flash将会在鼠标移动任何Sprite造成一些属性(x,y,宽,高等)的改变时,会强制自动重新渲染屏幕。当然,这仍然出现在片末,并且预渲染逻辑仍然在执行。 4 并不是每帧执行相同的时间片,你的操作系统有可能因时间片的分配导致不规则的渲染。比如你的帧率为20,每秒执行50片(也就是2帧5片)。那么FlashPlayer将会每5个时间片渲染2帧,并将遵循3-2-3-2-3-2片的渲染比率。 这些结论是在我们假设的20毫秒片即每秒50次的执行中得出的结论。而事实上,经常有5毫秒或者100毫秒的误差。 如果你想自己测试这个模型,最简单的办法是搞两个swf文件,一个帧率为1,另外一个帧率为100,让他们共同执行一个Timer,时间间隔设置为1毫秒。通过Timer改变显示对象的x属性,然后用trace追踪不同的事件,比如鼠标,EnterFrame,渲染。在过去的2年里,我知道了还有很多关于FlashPlayer信息无法从测试结果中得到,它并不那么透明。 |