Understanding Flash Player with Adobe Scout

1 篇文章 0 订阅
   Adobe Scout 是一款强大的Flash内存分析工具,可以观察到Flash Player后台正在运行的内容。从Adobe Scout上表现的内容,就可以知道Flash Player正在做什么、为什么这么做。只有如此你才能够更加迅速的想出修复使用Scout时发现的问题。

  本篇文章旨在让你对Flash Player的工作流程有一个基本的理解,并能够与你在Scout 中看到的信息关联起来。本文同时也是scout 使用流程指南,以便你能够查询在Flash Player不同活动的含义。如果你使用过Scout,并且有过“我可以看到‘X活动’消耗大量时间,但是‘X’是什么”的疑问时,这篇文章是适合你的。
  注意这篇文章并不是用户指南。如果你不知道怎么使用Scout,或者每个面板做什么,此时你需要阅读 [getting started guide](http://www.adobe.com/devnet/scout/articles/adobe-scout-getting-started.html)。

Flash Player 概述

 (描述略)
  • TimeLines(时间轴),在Flash ProFessional中编写。帧动画被一系类标签替代。帧标签是对每一帧行为的简单描述结构,比如围绕场景移动对象。每一个可视化操作,比
    如添加一个对象到到某一帧,或者使用Tween,都会被编码成一个帧标签到SWF文件中。
  • Scripts(脚本),使用ActionScript。被Flash Player 在某个时间点执行,例如:swf加载完成,timer运行,鼠标点击事件触发。你可以将代码附加到每一个独立的帧。
    当Falsh Player执行你的代码或是时间轴上的标签时,都会通知Flash Player运行各种各样活动。这些活动大致可以分为四类:

  • (Immediate activities)立即活动。当通知Flash Player立即执行这些任务时,播放器将不会执行其他活动直至上述任务执行完成。例如:创建一张新的图片,或者初始化一个Http请求。

  • (Ongoing activities)运行时活动。当你初始化这些任务后,Flash Player将会在后台持续运行,直到任务完成或者停止任务。例如:播放音乐,下载文件等。

  • (Defferd activities)延时活动。在代码或者帧标签中的操作不会被FlashPalyer立即执行。FlashPlayer会在一段时间后(但都在一帧时间内)执行较大的操作。例如:改变显示对象位置后,显示对象将会被标记为“(dirty)脏对象”,意味着该对象将会在一段时间后被重新渲染**>注意:如果对象状态没有发生变化时,播放器会使用缓冲中已有的数据进行填充屏幕。

  • (Implicit activities) 隐式活动,这些内建在播放器中默认运行的操作不需要请求。例如:垃圾回收,鼠标和键盘事件。
    当看这篇文章时,务必时刻记住以上内容。Flash Player不单只是执行ActionScipt;还有其他任务在运行!如果你将Flash Player当做你的个人助理,那么运行ActionScipt就像一次会议。就算是一个非常短的会议,Flash Player也会在之后执行所有给出的任务。渲染花哨的动画会消耗一些时间,除ActionScipt之外还有许多任务正在运行。

播放器实例和会话

你可能会好奇FlashPlayer怎样管理正在执行的所有不同活动。
当你在浏览器运行Flash播放器时,Flash Player一般运行在一个单独的操作系统进程。在同一个浏览器,所有的SWF都运行在同一个进程中,包括worker线程,并且Flash Player管理所有的SWF的执行,以便每一个SWF看起来都是独立运行的。每一个运行的SWF 都可以当做一个播放器的实例,在Scout中对应一个会话。对于Air程序,只有一个播放器实例,加上正在使用的wokers。

执行播放器实例
在Flash Player运行时,flashPlayer在不同的活动中切换。可能运行一段脚本程序、播放一段视频、渲染图形等等。确切的组合取决于当前发生了什么事件,哪些运行时活动运行在线程中,哪些活动被在间轴上运行,或被SWF中的代码请求。当所有的活动运行,Flash player 将会记录它正在做什么,并且计算当前正在消耗的资源,包括CPU时间、CPU内存、和GPU内存。这些测量数据将会发送到Scout,以便你能观察到当前正在运行什么。为最小化测量开销,Flash Player只测量和记录较大的时间消耗和内存占用。
在最基本的层面上,在任何时候Flash player 只会处于活动或非活动状态中。
  • 活动状态(Active):Flash player将会执行代码、渲染显示列表、处理鼠标事件等。

  • 非活动状态(Inactive):Flash Player进入等待状态,不在处理事物逻辑。可能被某些外部条件阻塞比如GPU,或者正在做一个简单工作(我的理解:在一帧时间内很快完成了分配任务,然后等待下一帧开始)。
    当使用Scout时,总时间(活动时间和非活动时间总和)在时间轴中被显示为灰色长条。为了简单的区分出每一不同活动消耗的时间比例,Scout将活动时间分为4个大类:

  • ActionSctipt(蓝色) – 代码运行时间和API调用的总时长。

  • DisplayList渲染(绿色) – 花费在操作显示列表的时间,比如栅格化、复制到像素屏幕。注意此处不包含使用不同Api进行渲染的stage3D。
  • 网络和视频(黄色) – 包含从网络下载文件、流媒体和视频解码的时间。
  • 其他(橙色) – 花费在除掉上述任务的总时间,比如垃圾回收,事件进程,和SWF解码。

要明白,Scout显示的是消耗的时间,而不是CPU时间是非常重要的。想象Flash player 坐在那里拿着秒表,记录每一个活动耗时。如果操作系统在活动中间中断Flash player进程,让其他应用程序运行一段时间,此时Flash Player将会记录到一个较长的耗时。在使用Scout时,为了得到一个更近精确的时间,最好关闭其他应用程序。

Flash Player 心跳
    许多Flash 应用程序,特别是游戏,需要处理大量的矢量动画。其基本原理是在一定的频率重绘屏幕--比如60次每秒--以便看起来像一个平滑的动画。为了更好的处理这种形式的编程,Flash Player 引入一个帧概念。在播放器内部,有一个跳动的心脏,---按照某一个频率执行一次称为帧频。两次跳动相隔的时间称作“帧”。在播放器中你可以使用任何帧率运行。帧频是SWF的一个属性并且在运行时可以动态修改。
编程过程中通常会监听一个Event.ENTER_FRAME事件,该事件在每一帧开始派发。如果你正制作游戏,您可以使用此事件处理函数来完成所有需要的定时工作,以保持游戏的运行。例如,您可以处理来自用户的任何输入,使用物理引擎更新游戏状态,最后渲染更新的场景。当你使用Scout分析时,时间轴上将会显示每一帧花费的时间。。考虑您要达到60帧每秒(60帧)帧率游戏。1秒有1000毫秒(ms),每帧你将有1000/60=16.7毫秒的预算。如果,平均每帧需要比这更长的时间,Flash Player将无法在你要求的帧率运行,您的游戏可能看起来抖动,并掉帧。在Scout的时间轴上,每一帧预算时间显示为水平红线,灰色条代表由每个帧所花费的总时间。
在一帧中,Flash Player将有许多不同的活动需要执行。首要任务是派发Event.ENTER_FRAME事件,并执行所有已注册的事件函数。在执行ActionScript代码时,这可能导致新的延期或正在进行的活动被添加到“待办事项列表”,比如重绘屏幕的一部分或开始一个新的文件下载。这些都将会在一帧中的某段时间后执行。此外,鼠标事件,键盘时间,以及其他事件可能在帧期间内触发,而这些都需要得到处理和处理。最终,Flash Player将在一帧中完成所有任务,直到所有任任务都被完成。然后,它坐在那里等待下一个心跳,并在之后的每一帧重复上述活动。
在Scout中,最需要注意的的是跨越红线的颜色条。这意味着Flash Player完成上述内容花费的时间比一帧预算的时间要多。换句话说,Flash Player一帧需要处理有太多的任务!如果所有的帧始终超出预算,那么你的播放器通常会掉帧(见图1),如果在Scout中有大量峰值颜色条,您的游戏将会出现卡顿现象。

图1

请注意,即使一帧耗时较短,Flash Player将会休眠(没有找到一个合适的名词)等待下一帧开始。这是一件好事,意味着你的flash不再占用设备,从而降低了功耗,并给出了CPU时间来执行其他任务。这也意味着你的内容懈怠内置到它,以便能够在低配设备上保证目标帧率。最终灰色条可以在红色线上下浮动。(见图二)

图二

下面一些细节需要注意:
    Flash player 最大可设置帧率为60fps。设置更高的帧率Flash player 也不会运行的更迅速。请记住,大多数显示器是不支持帧率超过60fps,所以设置更高的帧频是一大禁忌。Flash Player和操作系统紧密配合。你可以浏览网页的时候运行多个Flash player实例,并拥有不同帧率。Flash player不同实例之间会尝试同步唤醒时间,而不是在随机的时间内唤醒,减慢电脑运行速度。粗略的讲,播放器一秒内唤醒60次,在任一个播放器实例准备好后,都会开始新一帧。这意味着你的运行时间并并不会按照一秒60fps、24fps进行均等划分,那么你会看到灰色条最高峰值会在红色线上下浮动。只要平均帧率达到你设置的帧率时,那么都是正常的。(你可以在Scout选中某一范围的时间查看平均帧率)。如果你在Scout看到灰色条一直处于红线之上,即使其他色条(活动时间)始终低于它,那么在你的计算机上可能有其他应用程序正在使用CPU资源。请尝试关闭其他应用程序和浏览器窗口。

这里写图片描述


Flash Player组件

现在您应该对Flash Player的基本结构有一个大致的理解。现在我们可以通过Scout上显示的内容更深入的了解Flash Player。你会发现,顶级活动和活动序列面板将Flash Player按照行为进行分类。对于各个面板的的功用描述的非常详细,但有时候您需要更多的信息去发现问题的根源。下面将不同Flash Player活动细节做了更详细的划分。见图4

这里写图片描述
在使用Scout时,你可以只关注需要解决问题的部分内容,也可以阅读全文系统的了解Flash Player不同模块的工作流程。

ActionScript3和事件处理

    as3是Flash的脚本语言,他可以让你告诉Flash Player做什么。当你创建一个SWF文件,as3代码将被编译成可以被Flash Player理解的低级语言--ActionScript字节码。当您的SWF文件运行时,字节码将会被AVM(as3虚拟机)执行。AVM实现了一些核心功能,包括垃圾收集和异常处理,并作为Flash Player和ActionScript的联接桥梁。

的ActionScript是Flash的语言;它可以让你告诉Flash播放器怎么做。当你建立一个SWF文件,ActionScript代码被编译成一个称为ActionScript字节码Flash Player可以理解低级语言。该字节码,然后得到由ActionScript虚拟机(AVM),您的SWF运行时执行。该AVM实现的ActionScript的一些核心功能,包括垃圾收集和异常,也可作为你的代码和Flash Player之间的桥梁。
你可以使用ActionScript API和Flash Player进行交互。底层使用C代码来实现函数的调用、。在Scout中 ,API的调用会被显示在函数执行面板,你不需要关心底层实现。如果你调用API花费的时间较长,此时你应该减少函数的调用,或者减少代码逻辑的复杂度。

    在使用Flash Player调用ActionScript时,你需要告诉Flash Player什么时候执行你的代码。大部分时间,通过使用事件处理函数完成。当事件派发后,你注册的函数将会被调用执行。你可以创建自定义事件,使用EventDispatcher.dispatch()手动派发事件,通常您会经常监听其他外部事件,比如鼠标事件,键盘事件。 在Scout中涉及到这样的活动:


AVM活动包含代码执行活动和ActionScript语言特性相关的进程:
  • 垃圾收集 - 不像C和其他需要明确内存管理的语言,ActionScript内部实现了垃圾收集和释放的功能。每隔一段时间,Flash Player中运行一个垃圾收集器来扫描那些不再被引用的对象(有没有对他们的引用),并释放他们使用的内存。如果花费在垃圾回收上的时间过多,说明对象被频繁的创建和销毁。此时您可以尝试使用缓存或对象池来规避创建对象所消耗的时间。
  • 控制台输出(Trace):
  • 异常处理: 通过异常处理我们可以跟踪到在代码执行时的代码堆栈。因此,在Scout可以看到并不意味着代码发生异常。
  • 处理未捕获错误(Handling uncaught error):派发UncaughtErrorEvent.UNCAUGHT_ERROR事件到注册该事件的对象。

    最后,如果你在as3中调用其他版本as代码时还有一些其他活动产生:

  • AVM Bridge callback –as3调用as2时。

  • ExternInterface callback – 使用as3调用js代码。

显示列表渲染

    渲染显示列表是Flash Player渲染的基本方式。首先,从舞台得到一个空白画布,然后在画布上绘制不同的显示对象。显示对象主要包括矢量图、位图、文本,通过上述对象可以呈现丰富多彩的场景。无论是通过代码与显示对象交互还是在Flash Pro设置位置补间,您都不需要关注底层的渲染方式。Flash Player会帮我们将显示列表转化成具体像素显示到屏幕上。
    在编码过程中我们可以通过调用底层API,对显示列表进行变换操作。您可以认为这些变化是立即执行的。当调用API时,Flash Player会立即**更改显示对象**的状态,但屏幕上的显示并不会立即更改。相反Flash Player会将我们更改状态的显示对象标记为“脏”的,意味着它们需要重新绘制。在代码执行完成后,Flash Player才会进入渲染流程。在实际过程中,Flash Player会收集所有更改的显示对象,再完成计算后一同更新到屏幕。可以将这个流程想象成一个定格动画;在一帧内,在你调整完所有泥人的位置后,Flash Player现场拍照记录,屏幕将会在这一帧显示这张图片。

图5

  • 计算脏区域(Calculating dirty regions)–在渲染周期内通过扫描显示列表,找出所有被标记为“脏”显示对象(例如,正在移动的对象)。然后Flash Player最多生成3个包含所有脏对象的矩形区域。这3个矩形区域即需要被重绘的区域。即为在Scout DisplayList渲染栏中看到的红色区域。
  • 渲染脏区域(Rendering dirty regin)– 对于每一个脏区域,需要重新填充每一个像素点。Flash Player在内部通过显示缓冲区重新构建场景。渲染脏区域包含以下步骤:
    • 构建显示对象边缘(Building edges from DisplayObject)–Flash Player 会对显示列表再次扫描,找到所有和脏区域重叠的对象。每找到一个显示对象,都会被打散成一组边缘和填充对象(可以是纯色、渐变色、或者位图规划好空白区域和边缘的颜色属性)。如果该显示对象包含其他显示对象,上述操作也会被应用到子对象上。一般,Flash Player将不通层级场景平滑填充到不同区域。(应该是说不同层级会被合并到一层进行填充的意思?)。
    • 栅格化边缘(Rasterizing edges) – 到这步时,Flash Player 已经将边缘和颜色块都转化成实际像素点,并将脏区域划分成许多水平扫描线,包含每一个垂直像素点。每一扫描线都共享机器核心。Flash Player 每走一条扫面线,会基于不同边缘区域的填充情况去计算每个像素的遮挡情况。这一步骤的消耗取决于像素点个数,和绘制每一个像素点所花费的时间。纯色填充绘制最快;位图旋转缩放,不同透明度区域的混合会造成更大的消耗。
    • 应用滤镜(Applying filter) – 如果设置过任何滤镜,比如发光滤镜,阴影滤镜,这些滤镜都会被栅格化成图像。如果显示对象的子类应用了滤镜,该滤镜将会在父对象光栅话之前应用。Flash Player通过将子对象光栅化到一个单独的面(在Scout中DisplayList 显示为蓝色),并对其应用滤镜。这将会生成一个新的位图,当构建父容器边缘时,会将整张图作为一个原子填充到父对象中。
    • 复制到屏幕 (Copying to screen) – 在渲染阶段结束时,Flash Player将显示缓冲区中的数据拷贝到屏幕。这步消耗的时间取决于将要拷贝的像素个数。但也可能是在获得来自操作系统的锁的延迟。如果您在使用硬件加速,这意味着显示缓冲区已经在显卡上,Flash Player只需要告诉显卡显示。此处应显示为花在等待GPU的时间(更多信息请参见上GPU相关的性能问题的一些注意事项)。如果没有,请检查您是否正在使用最新版本的Flash Player(11.5或更高版本)。
      绘制含有许多边缘和不同滤镜的复杂图形是非常耗时的。尽可能的使显示列表轻量化以减少一帧中重绘脏区域的数量和大小。如果你当前绘制的显示对象层级嵌套复杂且很少修改(除移动外),可以通过缓存该对象提高渲染效率。将显示对象光栅化为cached surface,并只会在对象发生变化时重新生成cached surface。如果显示对象只有平移操作,设置cacheAsBitmap 属性。如果你需要旋转或者缩放该对象,则使用cacheAsBitmapMatrix(只支持在移动设备AIR中使用)。
      Scout将会显示以下和cached surfaces关联的活动(在DisplayList渲染面板 显示为橙色):
  • -

Rendering from cached surface – if a display object has a valid cache, Flash Player uses this rather than building and rasterizing its edges.
Updating cached surface – if you modify a cached display object or its children, this invalidates the cache, and it needs to be recreated. If Flash Player is spending too much time updating cached surfaces, it’s an indication that you’re using caching incorrectly. Caching should only be used on display objects that rarely change, otherwise it’s faster not to cache!
http://192.150.16.114/devnet/scout/articles/scout-memory-profiling.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值