:::: 菜单 ::::

Flash Player 10.1内部机制

本文是我在http://riaoo.com/?p=1658上看到后,转贴过来的,原文内容来自http://blogs.adobe.com/xwlin/2010/04/flash_player_101_-_adobe_max_2009.htmlhttp://blogs.adobe.com/xwlin/2010/04/flash_player_101_-_adobe_max_2009_1.html

演讲人: Lee Thomason (lthomaso@adobe.com)  翻译: 林晓伟 (xwlin@adobe.com)

序言

时间: 本月21号 地点:北京国际会议中心。 Adobe即将迎来为期2天的Flash平台技术峰会, 我将有幸作为Ely Greenfield辅助演讲人参与<<Flash Player内部机制>>这一话题的演讲和翻译工作, Ely Greenfield是Apollo Integrated Runtime部门的Senior Principal Scientist, 他在2007年Adobe Max大会上曾经作过这个话题的非常精彩的演讲,google上搜索到了一个参加07年Max大会的哥们对Ely本人及其演讲的评论,"我认为Ely的topic(Flash Player内部机制)在整个Max大会所有topic里是最棒的…" "Ely就是那个传说中闭着眼睛用三天的时间编写了Flex Charting Framework大部分代码的家伙"…

Adobe 09年的Max大会仍然有Flash Player内部机制这一话题,不过演讲者是Lee Thomason(另一个骨灰级牛人, Flash Player架构师, 外号Player Guy, 据说是Flash Player第一人), 这是一个非常有深度的话题, 演讲速度很快,一个小时的时间涉及到了player架构方方面面尽可能多的技术, 在这里我将他的大致演讲内容总结翻译一下, 供大家参考.

构建Flash Player

过去,手机版FlashLite和桌面版Flash Player是截然不同的两个独立产品,由两个相互独立的部门各自开发维护, FlashLite部门有自己的发展目标,产品定位及功能特性,项目的开发计划也由自己来决定。这给两个部门带来了很多的紧张情绪和挑战。因此Adobe决定将这两个部门合并,合并意味着即将发布的Flash Player 10.1手机版和桌面版将基于同一代码库构建

Lee在Max大会中提到大约20%的Flash Player代码仍然是平台相关的,这些代码针对于Palm, ActiveX, OS X, Netscape等做特殊处理,不同平台之间存在诸多差异因此实现100%的通用代码库是不可能的,但这仍然意味Flash Player代码库中80%的代码是平台无关的。

一个代码库,更多的Player类型.

统一player代码库更方便Adobe制定针对手机、浏览器、桌面等多种player的一致的发展战略,同时这也给Flash Player部门和开发者社区带来了新的挑战。

第一个挑战就是各平台之间的处理能力(主要是CPU)以及内存大小相差迥异并且这种差距愈演愈烈.一个服务器的8核CPU和掌上设备Palm Pre的处理能力大相径庭,而PC机浏览器平台可以提供几个G的内存但掌上设备只有20兆这将促使开发人员以截然不同的方式开发应用。注意:我们并不是说在PC浏览器上我们不需要考虑内存使用的问题,只是相比于掌上设备后者更为显著。

第二个问题也就是统一化界面面临的屏幕大小和像素深度的设备差异。今天,越来越多的应用程序跨设备运行,因此深刻理解有限的屏幕如何布局像素如何高效使用变得越来越重要。LCD显示器的像素深度(每平方英寸的像素数)要比手持设备小得多,这意味着一个40像素的按钮在你的LCD屏幕上看起来很大但在Pre上却太小了以至于无法使用。同样的,即使是分辨率相同的两种掌上设备像素深度仍然可能不一样,iPhone 3GS的屏幕大小3.5英寸,分辨率320*480,像素深度为163PPI,而同样分辨率的Palm Pre屏幕大小只有3.1英寸,像素深度为186PPI。因此如果我们只是考虑分辨率设计UI的话,那么player认为大小一样的两个按钮,在iPhone上的那个工作正常但在Pre上的那个就可能无法工作。

另一挑战来自于不同设备所支持的用户交互方式的多样化,有的设备支持键盘鼠标,有的设备支持多点触摸,等等,flash player需要理解不同的用户输入设备,我们做为开发人员需要理解输入设备多样化会给我们开发应用带来什么样的影响。在针对支持多点触摸的设备开发应用的情形下,我们需要知道手指并不是一个可以精确定位到像素的输入设备。Player要给我们提供最准确的相关信息,从最低层的原始数据到最上层的用户操作比如擦除、轻按。

最后一个来自于战略一致化的挑战在于用户对于应用的期待会根据设备的不同而发生变化。对性能和可用性的期待会基于用户当前是在使用手机还是桌面浏览器而发生改变。在手机上,一旦有新的来电当前应用必须在10毫秒内关闭,如果player做不到这一点,那么用户就会失望。

Flash Player本身并不是战胜所有挑战的秘方良药

以上分析的唯一结论是,我们不能寄希望于Flash Player解决所有的问题;事实上,作为开发人员,我们要深刻理解应用的发布平台,同时要知道良好适用于一个用户/设备组合的设计方案可能根本不适用于另一个。随着我们开始着手针对越来越多截然不同的设备平台进行应用开发,我们要始终把这些因素记在心里。

以上是这个话题的第一部分,在第二部分,我们将探讨执行模型和player体系架构,在第三部分,我们讨论一下ActionScript的第二代虚拟机做了哪些改进,第四部分我们将深入Flash视频和渲染系统。

理解执行模型

执行模型是指Flash Player在每一个帧周期中如何执行相应的指令操作。Flash Player后台事实上运行着n多线程,只是AS并没有给开发人员提供多线程编程模型。这意味着从概念上来讲我们要把Flash Player看做是单线程运行实体,有关这一单线程编程模型的优势/劣势的争论从未休止过,我不想对这一具有争议性的问题做过多评论,但请大家记住这一事实。

可变跑道(Elastic Racetrack)

可变跑道是Flash Player的帧执行模型,这个模型描述了在一帧的处理周期中,代码执行和帧渲染的工作是怎样彼此平衡的。Flash Player 9和AVM2对这一模型进行了一些改进,这一信息是基于对事件机制和渲染模型的研究总结出来的,完整的模型尚未被官方公布。

基本的跑道理论没有发生改变,在Flash Player执行一帧的周期里,前一部分时间用于执行代码,剩余时间用于渲染显示列表中的对象。每个执行阶段都可以根据实际需求增加执行时间来执行更多代码或做更多的渲染工作,而跑道的总长度也将相应增长

elasticracetrackexport 

在前一模型基础上发生改变的是每一阶段在一个微观周期里的样子以及他们怎样形成一帧。

AVM2是由Flash Player中一个叫做Marshal的元帅级组件所操控,Marshal负责将时间切割成Flash Player工作所依的基本时间片,在这里我希望澄清一下Flash Player的时间片跟swf文件运行时的帧速率没有任何关系,我们将最终看到Flash Player是如何将这些时间片合成为一帧。在Mac OS版Firefox中执行一个由Flex编译得来的swf文件,Marshal通常会将时间切割成19-20毫秒的时间片,时间片大小根据平台和浏览器的不同而存在差异.为方便我们接下来的讨论,我们假定时间片大小为20毫秒,也就是说Marshal每秒钟会产生不超过50个时间片,每个时间片中,五步可能的操作按如下顺序执行

  • 1.Player事件调度 – 比如Timer事件,鼠标事件,ENTER_FRAME事件,URLLoader事件等等。
  • 2.用户代码执行 – 所有侦听上一步相应事件的代码被执行。
  • 3.RENDER事件调度 – 在用户代码执行期间调用stage.invalidate()会触发这一特殊事件。
  • 4.最后的用户代码执行 – 侦听上述第三步特殊事件的用户代码此时被执行。
  • 5.Player更改显示列表。

marshalledsliceexport

Marshal如此反复的执行20毫秒时间片并在运行中决定下一步操作。一个时间片中执行的所有这些操作最终归纳为上述两段式跑道(代码执行,图像渲染)也就是我们所说的一帧。用户代码和失效操作填充在代码执行区,渲染操作填充在跑道的渲染区段。需要指出的是相关操作只能在Marshal预定的时间内发生,如果你的用户代码很短,那么Marshal仍然会在执行完用户代码后等待一段时间然后进入渲染阶段。

为了更好阐述哪些action被如何执行以及可变跑道如何被创建,请参考如下示例,分别描述了以5fps, 25fps和50fps帧速率工作的swf中时间片是如何被处理的。

framemarshalingexport

以上示例可以看出,不同的帧速率下,一个帧周期中的可变跑道会执行不同操作,例如对于5fps的swf,每帧处理10个用户action,1个失效action,1个渲染action;帧速率25fps的swf,每帧处理2个用户action,1个失效action,1个渲染action;对于50fps的swf,每帧只能处理1个用户action,1个失效action,1个渲染action。需要指出的很重要的一点是,某些事件只可能能发生在某些特定的时间片里,比如,Event.ENTER_FRAME事件只能在某一帧的初始时间片中被调度。

  • 一个时间片中代码部分和渲染部分都有可能过长而导致相应时间片大于20毫秒,这就是"可变"的含义,为了保证帧的播放速率仍然接近swf编译时设定的帧率,Marshal会选择丢掉一些时间片。
  • swf文件的播放速率不可能超过当前Flash Player切割时间片的速率,你可以为swf文件设定120fps的播放速率,但Flash最多可以按照50帧的速度播放(具体数值取决于当前系统的设置)。
  • 代码的执行频率可能比swf的帧率更高,播放一个1fps的swf文件,播放一帧时间为1秒,也就是50个时间片,但在每个时间片里,都会有触发鼠标或计时器事件,尽管只有最后一个时间片才会渲染,另外你可以选择通过调用函数updateAfterEvent() 提前渲染,但只能在鼠标,计时器和键盘事件处理函数中调用。在这种情况下,Marshal会认为当前帧已结束并从下一个时间片起进入下一帧。 最后,如果一个Sprite的外观属性比如width,height等发生变化而将鼠标从该Sprite上方掠过,Flash会进行强制渲染。
  • 如果帧率不是每秒时间片数量的整数因子,那么该平台的渲染时间间隔将变得不固定,比如帧率20fps的swf运行在50个时间片每秒的系统上,Flash Player的行为将是每5个时间片播放两帧,那swf的渲染频率将是2-3-2-3-2-3(时间片)。

(本文可能跟随原文作者追加内容而更新)

延伸阅读