Tagged: Browser Toggle Comment Threads | 键盘快捷键

  • Roger 8:27 pm on December 29, 2013 固定链接 | 回复
    Tags: , Browser, , ,   

    我的2013 – 年终总结 + 浏览器渲染发展的一些思考 

    又到一年的年末,秉承传统,继续为这一年写一篇总结的文章。今年依旧延续了进入公司后每年都更换不同小组的传统,下半年调到了内核渲染组,不过之前在技术研究组的工作也一直是专注于浏览器渲染相关的技术研究,所以这次调动也算是顺理成章了,工作内容基本上没有任何变化。

     
    今年一年以来的工作都跟硬件加速渲染有关,除了在不断完善和优化原有的硬件加速/图层混合加速的渲染架构,保证UC加速版的顺利发布外,另外最主要的工作就是设计和实现2D Canvas的加速渲染架构,从年初的初始实现版本到UC9.4加速版的版本,其间一共更替了三套不同的架构,而且每一次基本上都是完全推倒重来,但也解决了前一版本无法克服的一些内在缺陷,当前最新的架构基本上已经没有什么性能上明显的瓶颈,也足够灵活地根据不同的设备动态调整自己的行为,在兼容性,资源占用,性能这三者之间取得一个较好的平衡。
     
    回顾自己这一年的收获,通过研究Android图形子系统的底层实现,研究GPU和其它各种硬件的工作原理,自己对渲染架构和性能的理解也越来越深刻。“物尽其用,要事优先”是自己对高性能渲染架构的总结,一个高性能的渲染架构,设计者需要对硬件有相当的认识,知道如何将一个完整的渲染任务合理地进行分解,然后调度不同的硬件尽可能并发地完成它;要了解哪里是性能的瓶颈,哪部分是关键的任务,要保证关键任务优先获得资源的分配,尽可能降低瓶颈的影响。
     
    下半年开始,在和主管的工作总结中,还有职业等级评定的答辩会议上,都不断地被问到下面这两个问题,同时自己也在不断地进行思考。
    • 浏览器的渲染架构还有没有可能有更大的性能突破?
    • 浏览器能不能够成为一个承载游戏运行的良好平台,使得H5游戏能够跟原生游戏在同一层面竞争?
     
    浏览器的渲染架构还有没有可能有更大的性能突破?
     
    目前基于WebKit或者Blink内核浏览器的渲染架构,虽然各自的实现不太一样,但是整体架构设计都是由Apple奠定的,Apple当时把自己在MacOS上的那套Layer Rendering的渲染架构引入WebKit,率先在Safari上实现了Accelerated Compositing(图层混合加速),Chrome接着完成了自己的图层混合加速实现,而Android直到3.x的系统浏览器才开始支持,到了4.1才算是比较完善。虽然我不太了解Firefox的渲染架构实现,不过之前看过的一些文章介绍,思路总体上应该跟WebKit差不多。
     
    图层混合加速将渲染任务分解为Paint(绘制)和Composite(混合),绘制由WebKit内核自身使用CPU在一个独立的线程完成,绘制或者光栅化后的结果Layer Buffer(图层缓存)被发送到混合线程,由GPU来进行混合,而Blit(缓存的混合)则是GPU最擅长的工作,甚至可能不需要动用GPU的3D加速单元,使用2D Blitter就够了。
     
    这种架构主要的缺陷在于:
    1. 为了保证渲染性能和效果,浏览器需要大量的图层缓存,尤其对于是一些图层非常复杂,数量非常多的网页,这个问题在移动设备上更加明显;
    2. 由于绘制仍然使用CPU,对于普通的网页,绘制任务主要由图片,文本,各种不同图形的填充(使用纯色,渐变或者纹理)组成,CPU在大部份情况下的确做的比GPU更好,而且资源消耗更少,另外也有助于让GPU更专注于混合任务;但是对一些复杂的动态特效,像是CSS Filter的使用,单纯靠CPU会很困难,并且这种先绘制再混合的方式对于这些动态特效来说反而会造成性能上的损失,并且需要更多缓存;
    第一个问题,如果GPU能够支持一种无损压缩的纹理作为图层缓存,并且压缩可以高效实时的完成(甚至可以使用GPU,在纹理上传的同时完成压缩),就能够得到极大的缓解(对于网页这种大部份以文本和图形为主的位图,压缩率应该非常高,使用ZIP压缩1/10都是很正常的),不过在了解了一些纹理压缩相关的知识后,发现这一点的确不太可能,GPU主要还是为了游戏设计的,而游戏使用的都是事先生成的压缩纹理,并且GPU为了读取压缩纹理时的速度考虑,不可能支持可变压缩率,所以也无法支持无损压缩。
     
    第二个问题,可能的答案是将一部分绘制任务丢到混合线程直接由GPU来完成。不过困难在于两个方面:首先是否能够对绘制任务进行合理的分解,将其中一部分适合GPU完成的任务由GPU在混合线程直接进行绘制,而剩下的仍然保持原有的方式,简单说就是实现一种Hybrid Rendering架构;另一方面是使用GPU做缓存的混合是比较简单的,但是要直接完成复杂的绘制则比较困难,如果使用OpenGL,意味着要实现各种不同绘制的Shader,如果使用OpenVG这样的矢量图绘制API,貌似硬件兼容性和系统支持程度又有很多问题(Android系统本身是不支持OpenVG的,即使大部份GPU硬件上都支持)。除此之外使用RenderScript或者OpenCL这样的异构计算API来进行GPU加速绘制也是一种可能的方式。
     
    浏览器能不能够成为一个承载游戏运行的良好平台,使得H5游戏能够跟原生游戏在同一层面竞争?
     
    回答这个问题之前,先看一下现状,浏览器目前是通过2D Canvas和3D Canvas(WebGL)来支持2D/3D的即时绘图,这也是目前H5游戏的基础。在Android平台上,Chrome和UC都比较完整实现了2D Canvas的GPU加速,并且Chrome已经支持WebGL,UC接下来也会提供WebGL的支持,而WebGL本来就是对应到GLES。使用2D/3D Canvas开发H5游戏,存在的一些性能问题是:
    1. Canvas元素只是网页中所有元素的其中一个,所以它的绘制必须先绘制到一个单独的缓存中,仍然再跟其它元素的图层缓存进行混合输出,这个会带来一些额外的开销,导致性能损耗。不过这个问题还好,对PC来说这个额外开销不算高,而移动设备GPU的性能也越来越好(不过分辨率飙升过快也是一个问题…)
    2. 2D Canvas只提供了最基础的绘图API,难以通过这些API高效实现各种复杂的特效,比如说要实现一个粒子效果,不得不调用几十次甚至上百次drawRect或者drawBitmap,这样的效率非常低。而WebGL还好,可以允许游戏自己直接控制Buffer,自己编写Shader实现各种特效,直接交由GPU运行,从这点看,长远来说WebGL对游戏还是更有前途一些,不过相对来说,它的开发难度就要高不少(即使是使用2D Canvas开发的游戏,很多游戏也会在一些静态不需要太高性能的场景改成使用CSS+DIV来降低开发难度);
    3. 无论是2D Canvas也好,WebGL也好,它们都只提供了绘图API,离一个完整的游戏引擎相去甚远,而要依靠JS实现一个高性能的大型游戏引擎(包括物理运动引擎等)用来支撑一个大型游戏,受限于JS本身的性能,并且缺少底层硬件的直接控制能力,这点不得不说是最大的困难;
    对于第三点,Firefox和Chrome的解决思路完全不同:
    • Chrome通过Native Client允许原生代码直接在浏览器提供的一个受限环境里面运行;
    • Firefox通过ASM.js + WebGL的方式,遵循ASM.js语法的代码仍然是标准的JS代码,但是特殊的语法使得JS虚拟机可以直接将它们翻译成机器码,高效地运行;
    这两种方式先不谈技术本身的成熟度,共同存在的问题就是它们都太过复杂,游戏开发者不直接使用Cocos2D或者Unity3D这样成熟的游戏引擎开发原生游戏而使用Native Client或者ASM.js +WebGL,那简直就是脱裤子放屁,多此一举。
     
    有没有第三种解决问题的思路,我个人认为,浏览器自带游戏引擎(自行开发或者整合第三方的游戏引擎),然后通过一套标准的游戏引擎API供JS调用是一种可行的方式,这样JS就基本上变成像Lua这样的场景控制脚本,这种方式能够同时解决性能的问题和游戏开发难度的问题,当然它的问题是这样的游戏引擎标准API的制定和浏览器的实现还是相当虚无缥缈的事情……
     
    除了性能问题,H5游戏还有打包,发行等问题,不过这些可以通过打包应用(Packaged App)和Web App Store来解决。
     
    最后是我这一年写的比较满意的一些文章:
    1. Why Your Android Apps Suck https://plus.google.com/104793567654398886385/posts/TEr9MYV7tVy
    2. Android GraphicBuffer Introduction and Its Usage in Rendering https://plus.google.com/104793567654398886385/posts/j1LcfHAr5BS
    3. High Performance Canvas Game for Android(高性能Android Canvas游戏开发) http://tech.uc.cn/?p=2414
    Advertisements
     
    • Luin 8:49 下午 on 十二月 29, 2013 固定链接 | 回复

      收获很多,多谢

    • Luke 12:42 上午 on 十二月 30, 2013 固定链接 | 回复

      好习惯啊,而且都是干货。
      游戏是一种对浏览器App较高强度的考验,而且前景不错,以游戏的性能来作为评价指标也不失为一个好办法。
      顺着你的思路,我觉得优化空间应该还是有的:
      1. 纹理方面: a. 元素很多的页面是否做到了纹理拼接和压缩?(但对应的缓存应该还是需要的吧)
      b. 纹理压缩算法本身可以优化。一方面可以考虑并行运算的优化,另外一方面各种算法在内存消耗和运算消耗方面可以做trade-off。
      2. 更多元素使用GPU绘制,包括css3的效果等。理论上好像基于加速的skia就好?
      3. js引擎的继续优化。
      针对游戏开发,我觉得使用游戏开发套件或者引擎来开发肯定会是主流了,基于WebGL作为图形引擎的应该会成为主流,不用过分担心2D游戏的效率问题。
      Native Client技术很好,但暂时来说我觉得和Android NDK之于SDK一样,作为辅助或者完成一部分关键功能比较合适,主流的开发环境还是JS+HTML5。不过谁知道以后会不会有NaCL的游戏引擎?再说了Js后端也可能用PNacl/LLVM啊。
      从实用的角度来说,UC还可以发布一个基于浏览器的游戏引擎。

    • 艾楠 3:11 下午 on 三月 31, 2014 固定链接 | 回复

      好习惯!~

    • 韩国女装品牌网站 12:32 下午 on 三月 25, 2016 固定链接 | 回复

      世间有许多事功亏一篑的主要原因就是意志不坚定,不能坚持到底。现实生活中,如果没有坚定意志,我们就不能享受成功的幸福。

    • 韩国食品网上商城 12:36 下午 on 三月 25, 2016 固定链接 | 回复

      成功的人,是在无数次投资失败后站起来的。

    • 韩国时尚购物起义 1:08 下午 on 三月 25, 2016 固定链接 | 回复

      对投资而言,欲速则不达

    • 韩国创意设计用品网站 8:36 上午 on 六月 29, 2016 固定链接 | 回复

      像采金一样追求知识。

  • Roger 9:24 pm on August 12, 2013 固定链接 | 回复
    Tags: , Browser, , , ios, ,   

    [译文]关于移动Web性能的5个神话 

    译者前言

     

    这篇文章(http://www.sencha.com/blog/5-myths-about-mobile-web-performance/)由Sencha的CEO  Michael Mullany所写,主要是回应早前的一篇引起较多关于移动Web性能讨论的文章“Why mobile web apps are slow”(原文译文),作者的主要观点是“Why mobile web apps are slow”文中给出的数据虽然基本正确,但是对数据的解读却存在误导的成分,并且只考量了JavaScript的性能,而对移动应用来说更关键的Graphics性能并没有被考量在内。并且移动应用性能的提升不仅仅会得益于浏览器提升JavaScript的性能,还会得益于更高程度的GPU加速渲染,多线程并行化处理等等。

     

    译文

     

    我们最近听到了一些在不断重复的关于移动HTML性能的神话,但是这并不完全准确。就像那些流传已久的都市传说一样,它们听起来似乎有理有据,让人信服。但是这些神话是基于不正确的前提,对于原生应用和Web应用的软件堆栈之间的关系的概念是错误的,只是一些因为曲解了数据而推导出的漫无目的的观点。我们认为根据我们多年收集的一些性能数据和对移动Web应用进行性能优化的丰富经验,对这些神话进行澄清是十分重要的。

     

    神话#1:移动Web性能主要是由CPU主导的JavaScript性能所决定的
    真相:大部分Web性能是由浏览器对渲染流水线的优化,DOM操作的速度和使用GPU加速的程度来决定的。更快的JavaScript性能的确不错,但它很少会成为性能的瓶颈。

     

    神话#2:依赖CPU的JavaScript性能仅仅因为硬件的提升才变得更快(aka 摩尔定律)
    真相:在过去4年里面50%以上的JavsScript性能的提升是得益于软件上的优化,而不是硬件上的提升。甚至单线程的JavaScript性能还在不断提升,更不用说现在很多应用开发者通过使用Web Workers来利用多线程提升性能。

     

    神话 #3:移动浏览器最近的性能优化已经基本停滞,未来也没有更多上升的空间
    真相:每一个移动浏览器都在一些特定的领域比起其它浏览器在性能上有10倍-40倍的提高。Surface的SVG性能比iPhone高30倍。而iPhone的DOM操作性能是Surface的10倍。所以对每个浏览器来说,仅仅做到向其它浏览器表现优秀的领域看齐,就有很多性能提升的空间。

     

    神话 #4:移动应用很难再从未来的硬件性能提升中受益
    真相:在过去三年里,每一次硬件更新换代都会带来JavaScript性能的飞跃。不但浏览器的单线程性能仍然在不断提升,并且还会因为更快的GPU速度,更快的内存带宽,和通过多线程并行化处理更充分地利用多核CPU来不断提升性能。越来越多的浏览器已经开始更多地利用并行化来减轻主线程的负担,比如说:Firefox使用了单独的混合线程;Chrome并行化处理HTML解析;还有IE把JavaScript的JIT编译放到了其它线程

     

    神话 #5:JavaScript的垃圾收集对移动应用来说是性能杀手
    真相:这种说法曾经是正确的,不过现在的状况已经不太一样。Chrome在2011年的Chrome 17引入了增量垃圾收集机制Firefox去年也实现了同样的特性。这个特性将每次GC暂停的时间从200ms降到了10ms —— 相当于丢掉一帧 vs 一个可以明显感知的停顿。避免垃圾收集事件的确可以显著提升性能,但是只有你还在使用桌面Web开发模式或者在一个老旧的浏览器上运行,垃圾收集才会成为性能杀手。以我们在Fastbook(一个Facebook HTML5应用的克隆)使用的关键技术为例,通过建立一个DOM节点的对象池来回收不再使用的DOM对象并循环使用,我们成功避免了创建新对象的开销,同时也避免了因为删除旧对象而导致GC。浏览器的确很有可能提供了一个性能非常糟糕的垃圾收集器(比如说旧的IE),但这并不是支持垃圾收集的语言比如JavaScript(或者Java)的天生的无法克服的缺陷。

     

    OK:关键要素

     

    首先,让我们回顾一下最基本的概念。从5万英尺的高度往下看,浏览器本身是构建于操作系统之上的一个丰富和复杂的抽象层。而Web应用混合运用标记语言,JavaScript脚本语言和样式表,使用这个抽象层来创建应用的体验。这个抽象层本身需要额外的性能开销,而开销的多少很大程度决定于你使用抽象层的哪一部分。抽象层的某些部分更快是因为它们离操作系统的系统调用或者某些系统库的调用更近(比如说Canvas2D on MacOS)。另外一些部分会比较慢是因为它们无法直接映射到底层的操作系统,并且它们天生就十分复杂(DOM树操作,JavaScript对象属性访问的原型链遍历)。

     

    很少有移动应用是计算密集型的:没有谁会试图在iPhone上计算DNA序列。大多数应用有着一个合理的响应模型。用户执行一个操作,然后应用会马上回应一个30fps或者更高帧率的视觉动画,然后在几百毫秒之内完成任务。只要应用满足上面的要求,没有人会在乎应用基于的抽象层距离最底层的硅晶圆之间到底有多远。从这点来说,单纯地比较原生应用的抽象层和Web应用的抽象层意义并不大。

     

    对于Sencha来说,我们知道一个优秀的开发者使用移动Web技术和基于一个现代的Web框架比如Sencha Touch,是可以创建出优秀的应用体验的,它运行的足够快,满足用户的期待。并且过去3年的移动性能飞速提升的趋势也使我们深受鼓舞。我们很乐意跟您在接下来的文章里分享一些相关的数据。

     

    但是我们的本意并不是说移动Web应用能够运行的和原生应用一样快,或者它们能够在性能上能够与桌面Web应用相媲美。这不是真实的。移动设备的硬件性能比起桌面设备要慢5倍到10倍:CPU性能比较低,缓存层次结构过于扁平,缺少多级缓存的支持,网络链接的延迟也很高。并且任何软件抽象层本身(比如浏览器)都需要付出额外的开销。其实这不仅仅是Web应用开发者的问题。iOS原生应用的开发者一样可以告诉你,当iOS CoreGraphics在第一款视网膜iPad上性能很低的时候,这使得他们相当一部分人不得不抛弃CoreGraphics而直接使用OpenGL。

     

    进一步追溯神话的真相

     

    通过过去三年持续对Sencha Touch在数据驱动应用中的使用进行性能优化的经历,我们可以很自信的说,我们很少会被最原始的JavaScript性能所困扰。仅仅是在构建Sencha Touch布局系统时,因为Android 2.x的JavaScript性能太差,使得我们改用了Flexbox。

     

    更多时候,我们碰到的问题是DOM操作太慢,浏览器渲染引擎性能比较差和垃圾事件堆积过多无法及时处理。而这些局限基本上都是因为浏览器的架构设计者和开发者造成的,跟JavaScript语言和JavaScript引擎本身并没有本质的联系。举个例子来说,有一次我们和浏览器开发者一起优化浏览器性能,我们最终在某个特定操作上(颜色属性的改变)获得了40倍的性能提高,而这之前是我们的滚动列表实现的性能瓶颈,而类似的例子还有很多。

     

    在iOS和Android上的JavaScript性能

     

    虽然我们说过JavaScript性能其实对于移动设备来说并不是那么重要,但是我们还是希望可以推翻它并没有得到改善的神话。下图是SunSpider测试(越低越好)在iOS上过去4年的得分(按照硬件版本和OS版本划分)。(很幸运,SunSpider是一个广泛被应用的测试,所以我们很容易就在网上找到旧的iOS设备的测试成绩)。2009年的时候,当时运行iOS3的iPhone 3GS得分是15,000 —— 非常的糟糕,跟当时的桌面浏览器的300-600的得分相差30倍左右。

     

     

    然而,如果你把iPhone 3GS升级到iOS 4,5和6,你就可以在同样的硬件上面体验到4倍的性能提升。(在iOS4到iOS5之间性能的巨大的飞跃主要得益于新的Nitro引擎。)实际上SunSpider成绩在iOS7上仍然会有所提高,只是基于保密协议我们这里就不再多说了。跟今天的桌面浏览器相比,最先进的移动浏览器大概还有5倍左右的性能差距 —— 比起09年的30倍已经是相当大的改进。

     

    如果需要了解更多关于iOS硬件和软件性能改进的信息,可以参考Anandtech去年10月份的评测

     

    在Android平台上也差不多有相当等级的改进。从我们的测试实验室,我们找到了一些可以认为是过去3年里面在当时比较有代表性的高性能机器。我们测试了下面4款手机:
    • 三星Captivate Android 2.2(2010年7月发布)
    • Droid Bionic Android 2.3.4(2011年9月发布)
    • 三星Galaxy Note 2 Android 4.1.2(2012年9月发布)
    • 三星Galaxy S4 Android 4.2.2(2013年4月发布)

     

    如下图所示,SunSpider的成绩在过去4年的提升非常明显。从Android 2.x到Android4.x就带来了接近3倍的提升。

     

    无论是iOS还是Android,这些性能提升都不仅仅是由于摩尔定律本身带来的。过去3年,如果按照摩尔定律,我们期望获得的性能提升大概是4倍左右(18个月提升一倍),但实际上却远远不止,所以软件上的优化的确起了相当大的作用。

     

    更多有意义的测试

     

    如之前我们已经提过的,SunSpider的测试成绩其实越来越不重要,因为它跟应用本身的性能要求关系其实并不大。相反,DOM操作的测试,还有Canvas和SVG的测试成绩对应用的用户体验关系更密切。(理想状态下,我们应该还要去测量改变CSS属性的速度,还有CSS动画,过渡动画和几何变换动画的帧率 —— 因为它们在Web应用中使用的更频繁 —— 不过由于缺少浏览器的支持,仍然无法准确地获取这些测试数据)

     

    第一个DOM操作测试:我们使用了Dromaeo Core DOM测试。下图是之前的4台Android设备上得到的测试成绩,我们把Captivates上的4项Core DOM测试成绩(Attributes,Modifications,Query,Traversal)作为1分,其它设备的测试成绩就是相对于Captivates的得分,然后取4项得分的平均值作为最终结果。

     

     

    如你所见,Android从2.x到4.x带来了3.5倍的性能提升,虽然S4比起Note2的提升幅度比较小。我们在iOS设备上也进行了Dromaeo测试。不幸的是,由于iOS无法降级,我们没法得到老的iOS版本的测试成绩,不过我们仍然可以看到随着硬件的升级,Dromaeo测试性能一样是稳步上升。并且有趣的是,不同的iOS6设备之间的Dromaeo性能提升幅度要大于它们的CPU速度提升幅度,这说明了内存带宽或者缓存的速度提升肯定带来了更大的帮助,所以才能比单纯依靠摩尔定律所能获得的结果更好。

     

     

    为了显示浏览器还有多少潜在的性能提升空间(仅仅是为了赶上其它浏览器表现优异的领域),我们还测试了Surface RT。IE槽糕的DOM操作性能一直困扰着我们,但这说明了Surface RT上的IE10在DOM操作上还有很大的改善空间。这也是我们之前打破的一个神话 —— “移动设备的软件堆栈本身已经足够好,未来没有太多的优化空间”。起码对于Windows RT来说,在DOM操作上还有10倍的差距需要去填补。(我们后面还会展现在哪些测试上,iOS表现不佳)

     

    图形性能

     

    除了展现JavaScript和DOM操作性能的巨大提升外,我们还想为您展现浏览器在Canvas和SVG上的性能提升。我们之前就发现了Canvas2D性能在同样硬件上iOS5比iOS4提升了5-8倍。甚至当iPad 2升级到iOS5后,一些局部测试提升了80倍。并且因为Canvas实际上是对iPhone上的CoreGraphics API的直接调用,所以当原生图形性能获得提升时,Canvas性能也获得了同样的提升。在下面的测试中,我们使用了mindcat Canvas2D benchmark来测试性能。这里,我们看到了随着iPhone硬件的提升(都运行iOS6),Canvas性能也在不断提升。

     

    请牢记,上图的显示的数据已经计入了iOS4到iOS5的性能飞跃。如你所见,上图显示出历代iPhone在Canvas2D上的性能提升达到了7倍之多,远比它们的CPU速度提升幅度要大(按照摩尔定律CPU最多也就提升了4倍),这也反映了iPhone的软件堆栈充分利用了CPU/GPU来提升自身的性能。移动Web性能的提升实际上有很大一部分是受益于GPU性能的提升和浏览器更多使用GPU进行图形加速。

     

     

    我们再来看看在Android上运行同样的测试,我们看到一些有趣的数据显示Android上Canvas性能跟CPU性能之间并没有必然的联系。从Android 2.x到Android 4.x上的性能飞跃主要是因为2.x的Canvas完全没有使用GPU加速。这再次说明了,仅仅是浏览器充分利用GPU加速就能够带来巨大的性能提升。

     

    SVG测试

     

    SVG是另外一个可以展现Web性能的广阔的领域。虽然不如Canvas流行(很大程度是因为Canvas已经足够快),SVG的性能随着硬件提升仍然在稳步提升。下图是来自Stephen Bannasch的一个测试,测试了绘制10,000线段构成的一个SVG路径所需的时间。再一次,测试结果显示了各代iPhone CPU/GPU性能提升带来的稳定的SVG性能提升(所有的iPhone都运行iOS6)。

     

     

    但是最大的差距还是源于软件本身:Surface RT比iPhone 5快了30倍(对比iPad4也是如此,虽然这里我们没有列出来)。实际上,Surface RT比起运行在我一年前买的Macbook上的Safari仍然快了10倍!这个差距是是否使用了GPU加速造成的,Window 8/IE10在SVG上充分利用了GPU进行加速,才获得了如此惊人的成果。只要浏览器开发者把更多原来由CPU完成的工作转移到GPU上面去,我们就有可能在iOS和Android上也看到同样的性能提升。

     

    除了上面的长路径绘制外,我们还运行了另外一个来自Cameron Adams的SVG测试,测试了500个不断反弹的小球的动画帧率。再一次,我们可以看到由硬件提升所带来的SVG性能的稳步提升。

     

     

    比起单纯的性能数据,最终的fps值更让人感兴趣。一旦动画超过了30帧,你就可以得到一个跟电影动画(24fps)相似的结果,这样的流畅度已经基本上可以让观看者满意。如果能够达到60帧,那你就会获得由GPU加速带来的极致流畅的体验。

     

    真实世界的性能:垃圾收集,动态语言和更多

     

    我们希望之前的移动性能探索之旅已经说明了一些事情,也打破了一些神话。我们希望为您展现下列真相:
    • JavaScript的性能持续地快速提升
    • 性能的提升由硬件提升和软件优化同时驱动
    • 虽然高性能的JavaScript是一件好事,但实际上大部分Web应用的性能跟JavaScript性能的关系甚少
    • 幸运的是,其它影响Web应用性能的领域,像DOM操作,Canvas,SVG的性能也在飞速提升

     

    虽然我们可以展现一些高速摄影机下的动画测试,不过实际上所有移动Web应用的开发者都清楚,CSS动画,过渡动画和属性修改的性能从Android 2.1开始已经得到极大的提高,并且它们还在不断提高。

     

    之前我们已经澄清了一些不真实的论断,现在再让我们做一个最终的说明。我们不断听到的各种传言汇总而成的最终结论是“移动Web应用总是很慢,这是因为JavaScript是一种低性能的动态语言,并且垃圾收集机制对性能是一个极大的伤害”。应该说这个结论本身并不是完全错误的。不过如果你的Web应用使用类似Sencha Touch这样的框架来动态产生DOM内容,一个很大的优势在于,我们会在浏览器之上,在特定的应用上下文下,合理地去管理对象的创建和销毁,包括事件对象。这样即使你的应用需要展现无穷尽的数据内容(通过表格,列表或者转盘),我们通过回收DOM对象,过滤多余的事件,对要执行的动作进行优先级排序等优化,可以帮助您的应用获得60fps的视觉动画体验。

     

    如果没有一个中间层进行类似的间接处理,的确很容易得到非常糟糕的移动Web应用体验 —— 就像Facebook移动Web应用的第一个版本一样。我们相信如果应用直接使用类似jQuery Mobile这样直接操作底层DOM模型的UI框架时,在可见的未来的确会持续受到性能相关问题的困扰。

     

    汇总

     

    文中包含了大量的数据和覆盖了不同的主题,最后在这里让我们再总结一下。如果您是一位开发者,您应该可以从这篇文章了解到:

    • 移动平台的速度不及桌面平台的1/5 — 较慢的CPU,还有受限的内存大小和速度和较慢的GPU等等。这些都是无法改变的事实。
    • 移动平台的JavaScript + DOM的访问速度越来越快,但是你始终应该把iPhone 5看作跟2008年在桌面电脑上运行的Chrome 1.0一样 (即比桌面版的IE8快5-10倍)。
    • 移动Web应用的图形性能随着浏览器更多使用GPU进行图形加速和其它通用软件优化,已经基本可以实现30帧每秒的动画。
    • 垃圾收集和平台渲染性能有限的问题仍然会使你困扰,所以使用一个类似Sencha Touch这样的抽象框架来获得更佳性能是十分有必要的。
    • 充分利用移动Web平台提供的远程调试器和性能监控能力:像Chrome for Android现在已经提供了一个不错的fps计数器,还可以显示需要混合的图层边界,这可以告诉你哪些网页内容实际上已经生成了贴图并由GPU负责绘制,还有贴图被加载的次数。

     
    我们希望对这些性能数据的回顾能够帮助我们打破一些虚假的神话。我需要感谢在Sencha的所有人对这篇文章的贡献,包括Ariya Hidayat 的审阅和提供了大量关于浏览器性能优化的文章链接,还有 Jacky Nguyen关于Sencha Touch的抽象层如何进行性能优化的一些实现细节。

     

    翻译后记

     

    喔,终于翻译完了,以前还没有翻译过这么长的文章,没想到还真是一件累死人的事情。每一句话都需要斟字酌句细细体会字面下的意思,再用较为通顺的中文表述出来,无论是脑力还是体力都是相当大的摧残,说多了都是泪啊 =_=

     

    应该说要翻译这篇文章,甚至要读懂这篇文章,译者和读者都需要对浏览器内核的一些工作原理有所了解。
    • 比如文中多处强调JavaScript RAW performance和DOM Interaction的区别,这是因为虽然DOM Interaction虽然也是由JS去调用,但是对浏览器来说,实际上JS只是调用浏览器内核提供的JS Binding API,整个Interaction是由浏览器本身去执行的,所以不应该当作JavaScript本身的性能来考量。
    • 又如浏览器所构建的抽象层的不同部分直接或者间接映射到OS的系统调用或者系统库调用对性能的不同影响的说法要怎么理解?举个例子来说,Web应用开发者可以用DOM+CSS或者用Canvas实现同样的动画效果,下面分别是基于QuarkJS实现的两个同样的动画,一个基于DOM,一个基于Canvas,对于Canvas绘制直接使用OS本身的2D绘图库去实现,并且支持GPU加速的浏览器来说,Canvas动画的效率会比使用DOM要高的多,这是因为基于DOM和CSS的动画,浏览器通常需要进行重新计算样式,重新排版,重新光栅化,重新上传贴图,重新混合等这样一个复杂的流程,效率自然高不起来。再举一个例子,对于支持图层混合加速(Accelerated Compositing)和硬件加速的浏览器来说,对付CSS Transform这样的动画就是小菜一碟,因为对它来说这个动画就是不断改变元素所属图层的Transform属性,然后使用GPU重新混合的过程。而支持硬件加速的浏览器所谓的图层混合其实就是通过OpenGL进行贴图的这样一个过程。

     

    最后要说的是,文中的一些观点还是需要在一定的条件下才能成立的,并不是放之四海而皆准,这是读者需要留意的地方:
    • 大部分Web应用性能跟JavaScript性能关系不大,对它的要求不高

     
    是的,大部分是这样的,但不见得你的Web应用就是这大部分之一。实际上,对于有一定复杂程度的基于Canvas的Web Game来说,JavaScript性能很有可能成为它的性能瓶颈。这些Web Game的场景通常比较复杂,包含成百甚至上千的绘图对象(比如实现一个绚丽的粒子效果),需要在JavaScript里面构建一个成百上千个节点的Scene Graph。每绘制一帧,都意味着需要对这个Scene Graph进行遍历,访问每一个节点,更新它的状态,然后再调用Canvas API将它绘制出来。如果要达到30fps的速度,这意味着最多只有30ms左右的时间来完成每一帧(实际上应该没有那么多),即使不算Canvas API本身的绘制开销,单单是遍历和状态更新的操作就很有可能达到几十毫秒的量级了,特别是状态更新中包含大量的碰撞检测和物理运动计算的时候。

    • 通过并行化处理是未来浏览器有效提升性能的一个有效手段

     
    应该说,当前通过并行化处理充分利用多核CPU/GPU提升性能是浏览器内核技术研究发展的一个热点。但是并行化并不是银弹,指望它能够短期内戏剧性地大幅度提升浏览器的整体性能并不现实。

    1. 首先对于移动设备来说,iOS还好,但是Android由于自身的开放性,硬件水平参差不齐,低端硬件还有相当大的保有量,它们缺乏足够的资源去支持并行化,并行化对它们来说反而更糟糕。不过得益于像MTK这样的芯片厂商大力提升中低端设备的性能,现在的千元机性能已经跟几年前不可同日而言,大概再过多一两年这个问题应该就不再成为问题了。
    2. 其次并行化处理并不是想象中的那么容易,因为浏览器的大部分作业实际上都有某种程度的顺序依赖和上下文依赖,需要很多额外的处理才有可能实现部分并行化(毕竟不是数据处理,要做到完全并行化可能性极低)。这样的并行化需要额外的开销,并且只适应于部分场景,有一定的局限性。目前浏览器除了网络链接的部分,并行化程度最高的应该就是渲染了,除了图层混合会运行在独立线程并且主要使用GPU外,像Chrome,Android Browser都把光栅化从主线程剥出来,渲染性能的确从并行化中获益极大,不过也付出了额外的CPU/内存开销的代价。其它领域的并行化进展还是很慢,并且也难见有可能使得性能大幅度提升,比如Chrome在做的HTML解析和样式计算的并行化,最多也就能够减少网页从开始加载到第一次完整呈现的时间,对于整体性能提升意义不大。至于JavaScript,除了IE所实现的JIT并行化外,垃圾收集也是一个有可能剥离出主线程的领域,只是我个人对JavaScript引擎了解不多,不知道具体的技术难点在哪里。
    3. 最后还需要前端开发者有意识地去使用并行化,或者为了更好地支持浏览器的并发作业对自己的应用进行专门优化,比如说Web Workers可以让部分JavaScript代码运行在独立的线程,但在实际的网页里面使用的应该很少。

     

    最后的话

     

    作为读者,如果您能够一直看到这里,说明您应该对Web App/Game开发是有着真爱的^_^ ,所以不妨再看完这最后一节。从我个人的开发经验来看,一个经过充分优化的应用比起没有经过优化的应用通常会有非常明显的性能差别,如果您的Web App/Game对性能要求很高,并且主要运行在移动平台,那么性能优化对您来说那就更加重要了(移动平台可没有那么多可以挥霍性能的空间)。而为了帮助前端开发者更好地做好性能优化,Chrome提供了可称为逆天的神器Dev Tools,学会使用这套工具(推荐Code School上面的视频教程),然后使用它来对您的应用进行性能分析和优化,您会发现这才是真正能够获得戏剧性的性能飞跃的最大可能,这也是所谓的“求诸人不如求诸己”。

     
  • Roger 1:20 pm on April 20, 2013 固定链接 | 回复
    Tags: , , Browser, ,   

    国内Android手机浏览器内核未来竞争势态分析 

    前几天跟主管谈到这个话题,讨论得出一些结论,记录下来以备将来验证。国内手机浏览器在所谓“自有内核”的竞争上将会分为两个不同阶段,目前处于第一阶段。

    第一阶段是基于WebKit开发的“自有内核”,大概有两种方式,一种是WebKit内核代码(WebCore部分)直接跟主干保持同步,定期更新,平台适配层架构基本跟Android系统浏览器的适配层架构保持一致,将大部分系统浏览器适配层代码移植过来;另外一种就是直接全部采用Android系统浏览器的代码,包括适配层代码和WebKit内核代码,然后WebKit内核代码再逐步向主干靠拢(Android系统浏览器包含的WebKit内核代码版本比较旧);当然这两种方式发展到一定程度,其实是殊途同归的,相对来说,第一种方式对团队的整体水平要求更高一些。

    这一阶段的主要玩家就是UC和腾讯,百度也有参与,但是它的移动战略实在让人看不懂,感觉十分摇摆不定,按理说百度人和钱都不缺,但是始终没有下定决心大幅度投入手机浏览器领域,不知道在第二阶段是否会改变策略。

    其它国内桌面浏览器的主要玩家如360,搜狗,金山基本不参与这一阶段的竞争,360只在Android系统提供的WebView组件之上做了一层壳,搜狗和金山压根就没有什么大动作,360去年上半年还通过猎头在挖做手机浏览器内核的人,据说金山本来也准备投入,但是后来都改变了策略,更多把人力投入到桌面浏览器的竞争上面,在手机浏览器上,估计会直接参与第二阶段的竞争(听猎头说,传言金山本来已经成立手机浏览器团队,但是后来又合并回去全力做桌面浏览器)。

    第二阶段的“自有内核”会是基于Chrome&Blink,Chrome从WebKit主干分离出Blink,开始自己独自主导浏览器内核的发展,并且围绕Blink构建了一套Content API,用于将Chrome核心模块如多进程沙盒模型,渲染架构,网络堆栈,V8&Dart虚拟机和Blink内核封装在一起,用于支持Chrome本身和第三方基于Chrome&Blink内核的浏览器的开发(如新版的Opera)。

    从目前的状况来看,Chrome&Blink内核在Android平台大范围普及的时机还不成熟,主要在于Chrome&Blink内核本身还处于一个不太稳定的状态,Content API还在剧烈变化中,代码的性能优化和系统稳定性还有很多不足,并且Chrome本身的多进程架构对手机的性能有比较高的要求,包括CPU/GPU和内存大小,一些性能较差的手机连基本操作的流畅度都无法保证,另外默认的渲染架构强制要求4.0以上的系统版本。这些原因会导致第二阶段的竞争最早也会在明年才开始,开始贴身肉搏式的剧烈争斗预估也要到2015年。

    估计360,搜狗,金山会直接投入第二阶段的竞争,可能现在已经开始筹建团队和进行初期的技术准备。对他们来说,第一阶段已经基本尘埃落定,参与的意义不大,有限的人力还不如早点开始准备第二阶段,并且他们在桌面浏览器上本来就是基于Chrome在开发,所以第二阶段的竞争对他们来说反而在技术储备上会更有利。

    最终,从明年到2015年上半年这段时间,国内Android手机浏览器在“自有内核”上竞争的主要玩家会逐步增加到5~6家,因为各方都是基于Chrome&Blink进行二次开发,要获得相对于其它竞争者的技术优势会变得殊为不易。技术上的领先更多会体现在谁能更快跟进HTML5标准的发展,跟进由Google主导的Chrome&Blink内核本身的演进,一些局部的性能优化和更好地解决设备兼容性问题和系统稳定性问题。
     
  • Roger 5:04 pm on February 4, 2012 固定链接 | 回复
    Tags: Browser, , Firefox, IE, Opera,   

    5个浏览器和它们对应的交通工具 

    Firefox:面面俱到,功能强大,但是太多愚蠢的扩展让它几乎无法使用。

    image


    Safari:虽然性能不错,但是它的实际品质被它的使用者夸大了。

     

    image


    Opera:有一些人真的很喜欢它,但是其它人都认为它看起来真的很愚蠢。

    image


    IE:几乎没有任何作用,唯一的用途是用来被人口诛笔伐。

    image


    Chrome:非常快,嗯,就这样。

    image

     

    原文:5 Browsers and the Modes of Transportation They Resemble

     
    • fxwan 2:49 下午 on 二月 13, 2012 固定链接 | 回复

      IE: Worthless, but good for downloading other browsers.

  • Roger 10:38 am on December 14, 2011 固定链接 | 回复
    Tags: , Browser, HTML5, ICS   

    Android 4.0 (ICS) 浏览器的HTML5测试 

    这是一篇由Sencha团队关于对ICS浏览器进行HTML5(CSS3/JS)测试的评估文章,主要的结论是ICS的浏览器相对早期2.x,3.x的版本是一个巨大的进步,但是距离当前移动浏览器中的王者iOS5 Mobile Safari还是有一定的差距。Sencha团队是提供基于HTML5技术的Mobile Web App开发框架的领先厂商。

    Pros:
    1,HTML5标准的支持进一步完善
    2,CSS3动画有着比较完整的支持
    3,渲染的效果进步明显,像圆角,阴影的渲染更准确
    4,绘图效率的提升,交换和动画更平滑
    5,支持页面嵌入视频(inline video)

    Cons:
    1,不支持WebSocket,WebWorker
    2,Input类型标签支持不完整
    3,在动画和页面滚动的过程中仍然有页面闪烁的现象(在2.x上面非常严重,ICS相对好一些)

    Conclution:
    In summary, the Galaxy Nexus and Ice Cream Sandwich are a major step forward for the Android platform. Feature by feature, HTML5 support has gotten much better, rendering has become more accurate, and performance has gotten much faster. Although still behind the current HTML5 gold standard of iOS5, Android 4.0 is night and day compared to previous versions. We’re excited to see Google put this level of effort into Android’s web capabilities. And we hope they keep their foot on the gas! (And we’re keeping our fingers crossed that the Kindle Fire will get an upgrade to ICS in the New Year!)

    原文:
     
    • fxwan 2:25 下午 on 十二月 16, 2011 固定链接 | 回复

      主要是得益于Skia的HW acceleration,另外还有tiled rendering吧.4.0只是一个开始. overflow scroll不支持的web browser不是一个足够好的平台.

    • Roger 2:47 下午 on 十二月 16, 2011 固定链接 | 回复

      绘图速度的提升是一方面,对标准的支持也更好了。不过WebSocket,WebWorker,WebGL还是不支持。

    • fxwan 2:58 下午 on 十二月 16, 2011 固定链接 | 回复

      应该是还没有和chrome merge完吧.SE的手机在2.3上就支持WebGL了,而且速度还不错,没理解错的话应该还是没有accelerated compositor支持的情况下做到的.4.0上不支持可能主要是安全性和测试覆盖的问题吧.猜的.

    • Roger 3:56 下午 on 十二月 16, 2011 固定链接 | 回复

      SE手机有支持WebGL吗?那个型号的?

    • fxwan 4:03 下午 on 十二月 16, 2011 固定链接 | 回复

      Arc S 最新固件.好像有的其他型号也支持的.

    • fxwan 4:05 下午 on 十二月 16, 2011 固定链接 | 回复

      4.0.2.A.0.42

      • Roger 4:11 下午 on 十二月 16, 2011 固定链接 | 回复

        MK16i,Android2.3,测了一下HTML5 Test,不支持WebGL哦,177分,跟自带的浏览器一样,应该没改过。

    • fxwan 6:31 下午 on 十二月 16, 2011 固定链接 | 回复

      http://developer.sonyericsson.com/wp/2011/11/29/xperia-phones-first-to-support-webgl/
      可能固件不对吧,我的机器上已经可以使用了.

  • Roger 11:48 pm on April 11, 2011 固定链接 | 回复
    Tags: Browser, , Minijoe   

    MiniJoe UI架构和样式标注部分代码分析 



    image

    上图显示一个较为完整的HtmlBrowser的UI的部分类,其中:

    1. 在uibase包下面的xxxWidget是一组基本UI组件
    2. 在html包下面的xxxWidget是页面元素对应的UI组件
    3. css包下面的类用于CSS解析,生成解析后的结果

    一些类的具体职责如下:

    Widget

    1. 所有UI组件的根类
    2. 也包含了容器部分的逻辑

    TextWidget

    1. 用于显示文本的Widget

    ScrollWidget

    1. 在Widget的基础上提供了滚动支持的逻辑

    Window

    1. 定义了一个顶层窗口的接口,由具体的窗口类实现
    2. (minijoe的Window的实现跟其它GUI框架稍微有些不一样,Window不是一个继承自Widget的UI组件,而是一个接口,具体的实现类需要在自己内部定义一个默认的UI组件布局和对应的事件路由逻辑)

    HtmlScreen

    1. 实现了Window接口,作为顶层窗口
    2. 继承Canvas,提供屏幕输出和事件处理相关的逻辑
    3. 包含一个HtmlWidget,用于展现一个HTML/XML页面

    HtmlBrowser

    1. 继承MIDlet
    2. 处理命令

    TextFragmentWidget

    1. 用于显示文本片段的UI组件
    2. 包含一个Element的引用回溯对应的文档树的Element节点

    BlockWidget

    1. 对应页面的Block元素
    2. 可以包含其它BlockWidgets(包括InputWidget 和 TableWidget)和TextFragmentWidget
    3. 包含一个Element的引用回溯对应的文档树的Element节点

    InputWidget

    1. 对应页面的Input元素,包含输入框,组合框,按钮等

    TableWidget

    1. 对应页面的Table元素,展现一个表格

    HtmlWidget

    1. 对应整个页面(可以看作是对应Body元素)
    2. 包含一个Body元素的Element成员,该Element展开构成了一颗文档树(Body Element还不是根节点,它的父亲为Html Element)
    3. 包含一个样式树的根节点styleSheet,该成员用来读取样式表数据生成完整的全局样式树
    4. 负责整个页面的资源加载和管理,如图像资源,CSS/JavaScript脚本等
    5. 包含一颗由BlockWidgets/TextFragmentWidget组成的UI组件树
    6. 负责处理用户跟页面的交互(可能委托外部的处理器进行处理)
    7. 负责处理JavaScript,提供一个JavaScript执行的环境

    Element

    1. 作为文档树的一个节点,包含该节点的内容和属性(如class, id 等)
    2. 可以包含子节点,在minijoe里面只区分两种节点,最简单的文本直接用String表示,其它则用Element表示,Element的子节点可以是其它Element或者String,所以文档树任意一个非叶子节点一定是一个Element,而叶子节点可能是一个String也可能是一个Element
    3. 同时包含样式数据,所以Element构成的树,即做为文档树,在进行样式标注后也做为作为渲染树而存在,在minijoe里面没有像DOM一样的单独的文档树

    CSSTokenizer

    1. 识别CSS文本中的标记的解析器

    Style

    1. 对一个规则集合块(Rule Set Block)或者仅仅一条声明进行解析后产生的结果
    2. 包含一条或者多条声明的数据,每条声明对应一个属性和值对
    3. 可以通过set方法将两个Style按覆盖模式进行合并
    4. 可以通过inherit方法将两个Style按继承模式进行合并

    StyleSheet

    1. 包含多个Style,对应同一个选择符(Selector)
    2. 包含多个StyleSheet的哈希表,对应不同的选择符和不同类型的选择符,形成一颗样式树
    3. HtmlWidget里面的styleSheet成员为该页面的样式表数据解析后所产生的样式树的根节点

    HtmlWidget页面解析和渲染的一个简略过程:

    1. 解析页面数据生成文档树
    2. 解析CSS数据生成样式树(1,2可以交错进行)
    3. 使用样式树对文档树进行节点样式标注,自顶向下,先根遍历,最后产生的完整节点的样式数据保存在computedStyle成员中(minijoe支持多遍样式标注,每次更新样式树时都会重新标注,并根据一些条件判断是否需要重新生成UI组件树)
    4. 使用样式标注后的渲染树(样式化的文档树)生成UI组件树,每个UI组件都包括一个Element的引用回溯对应的文档树节点
    5. 生成UI组件树之后,HtmlWidget需要重新计算布局,确定每个UI组件的位置和大小
    6. 在HtmlWidget内部显示这颗对应页面渲染树(样式化的文档树)的UI组件树
    7. 在UI组件绘制自身的过程中,它需要从对应的Element的computedStyle取出绘制所需要的样式数据

    HtmlWidget生成样式树的过程:

    1. 在解析页面数据生成文档树的过程中,如果碰到STYLE元素,并且媒体类型(media type)匹配 ,Element会请求HtmlWidget将这段样式直接读入它的styleSheet成员
    2. 在解析页面数据生成文档树的过程中,如果碰到LINK元素,并且媒体类型(media type)匹配 ,Element会请求HtmlWidget加载该外部资源
      1. HtmlWidget会请求资源读取线程读取该资源文件(异步)
      2. 当资源读取完毕,资源读取线程会调用HtmlWidget的addResource方法加载资源
      3. 当资源是CSS样式表时,HtmlWidget会将该资源读入styleSheet成员
      4. 如果这时文档树已经生成完毕,则进行样式标注,否则等待文档树生成完毕后进行样式标注
      5. 如果文档树已经标注过,则重新进行样式标注,并且根据需要选择是否重新生成UI组件树
    3. 如果在解析样式表的时候碰到at规则 import,并且媒体类型(media type)匹配,StyleSheet会请求HtmlWidget加载该外部资源,执行第2步的操作

    HtmlWidget对文档树进行样式标注的过程(实际上对文档树的样式标注可以从任意元素节点进行,不过对于HtmlWidget来说,要对整个文档树进行完整的样式标注是从Body元素节点开始):


    1. 当文档树生成完毕或者styleSheet成员所指向的样式树更新时,则进行样式标注(applyStyle),支持多遍标注
    2. 调用Body Element的apply方法进行样式标注,对文档树的样式标注是一个对树进行先根遍历的过程
    3. Element的apply方法接收applyHere和applyAnywhere两个参数,它们都是StyleSheet的队列,applyHere表示可用于当前元素的样式表,applyAnywhere表示可用于当前元素和它的所有子元素的样式表,HtmlWidget在调用Body Element的apply方法时,就把styleSheet成员放入applyAnywhere中作为参数
    4. 元素节点的样式标注最重要的一个步骤就是从通过参数传递的可用样式表集合中收集样式(StyleSheet的collectStyles方法):
      1. 可以应用于当前元素的样式集合(queue)
      2. 可用于子节点和后代节点的样式表集合(childStyles和descendantStyles)
      3. 其中applyAnywhere里面的样式表会直接放入descendantStyles中传给子节点
      4. 在collectStyles方法里面,需要对元素的name,id,class和其它属性进行查询,以收集到匹配的样式,如果不需要支持其它属性,理论上可以传name,id,class Strings来代替Element实例
    5. 产生当前元素的最终样式
      1. 对收集的可以应用于当前元素的样式集合进行覆盖式合并,按照权重由低到高的优先序(权重高的样式覆盖权重低的样式)
      2. 如果当前元素有style属性,用该属性的样式数据对第1步结果得到的样式进行覆盖式合并(style优先)
      3. 使用第2步的结果跟父元素的计算后样式computedStyle进行继承式合并
      4. 如果当前元素有其它inline的样式数据,将这部分数据抽取合并到第3步的样式结果里面(applyHtmlAttributes)
      5. 把最后的结果作为当前元素的计算后样式computedStyle,当前元素的样式标注就结束了
      6. computedStyle里面的数据会用于UI组件树的布局和渲染,如果没有UI组件树,则需要直接从computedStyle里面把样式数据逐个取出来放到确定的地方
      7. 其中还有一些值的计算可能需要依赖于外部传入的参数,如使用的字体的高度,宽度,盒子的大小,使用的DPI值等
    6. 继续标注当前元素的子元素,childStyles变量作为applyHere参数,descendantStyles变量作为applyAnywhere参数
    7. 决定是否需要重新生成UI组件树
     
c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
回复
e
编辑
o
Show/Hide comments
t
返回顶部
l
Go to login
h
Show/Hide help
shift + esc
取消