Atitit 浏览器tech原理与概论 目录 1. 浏览器概述 1 1.1. 浏览器野史 UserAgent列传 1 1.2. 浏览器趋势 1 1.3. 浏览器大战 1 1.4. 三次浏览器大战 2
Atitit 浏览器tech原理与概论
目录
5.3. 5.3.3 RenderLayer树的构建 96 4
7. Line 45: 第7章 渲染与硬件加速 137 16
8. Line 93: 第9章 JavaScript扩展接口 176 17
9. Line 141: 第11章 浏览器调试工具 218 17
作者:: ★(attilax)>>> 绰号:老哇的爪子 ( 全名::Attilax Akbar Al Rapanui 阿提拉克斯 阿克巴 阿尔 拉帕努伊 ) 汉字名:艾龙, EMAIL:1466519819@qq.com
转载请注明来源: http://blog.csdn.net/attilax
多核,多useragent,自定义ua
参考浏览器大战_百度百科.html
参考一图看尽史上三次浏览器大战 _ 雷锋网.html
- 渲染引擎的组成:HTML解释器、CSS解释器、布局(Layout)、JS引擎、绘图等
- Blink和Webkit的不同:
- 跨进程的iframe:为了解决iframe潜在的安全问题,为iframe创建一个单独的沙箱进程
- 将DOM引入JS引擎中,提升js访问DOM的性能
- 接口的修改、性能优化等
- 浏览器和对应的渲染引擎:
Trident | Gecko | Webkit
:------------: | :-------------:
IE | Firefox | Safari Chrome Android浏览器 ChromeOS等
- Webkit渲染过程:
- 通过资源加载器加载URL对应的网页
- 网页被交给HTML解释器转变成Token
- HTML解释器依据Token构建节点,形成DOM树
- 如果节点是js代码,调用js引擎解释执行
- 如果节点是图片、css、视频等资源,会调用资源加载器来加载它们,因为它们是异步的,不会阻碍当前DOM树的继续创建;如果是js资源,则需要停止当前DOM树的创建,直到js资源加载并被执行后才会继续DOM的创建。
- 由于有些资源是异步的,所以DOMContentLoaded和onLoad事件一般不是同步的,前者要完成的早一些。
- DOM构建过程中会执行js代码,因此需要注意js的位置,防止在DOM还没构建的情况下被js代码访问。
5.1 WebKit网页解析概述 88
5.3 HTML解析过程 90
5.3.1 DOM树的构建 90
5.4.1 CSS文档结构 97
5.4.2 CSS解析过程 99
5.4.3 CSS规则匹配 100
- 第6章 排版布局 104
6.1 CSS盒模型 104
6.2 定位与包含块 106
6.3 Render类的核心对象 111
6.4 Render树创建流程代码分析 121
6.5 Layout流程代码分析 123
6.5.1 计算大小 123
6.5.2 确定位置 127
6.5.3 简单例子 130
6.6 绘制流程分析 13
第三章 Webkit架构和模块
- 浏览器是多进程的,包括:Browser进程、每个网页的Render进程、插件进程、GPU进程等进程:
- Browser进程和页面渲染是分开的,这保证了页面渲染的崩溃不会导致浏览器主界面的崩溃。
- 每个网页是独立的进程,保证了页面之间相互不影响。
- 插件进程的问题不会影响浏览器主界面和网页。
- GPU加速也是独立的。
- 浏览器中的进程基本上是多线程的,如Browser进程包括UI线程和I/O线程等,网页的Render进程包括渲染线程和I/O线程等,GPU进程包括I/O线程和GL线程等:
- Browser进程收到用户的请求,首先交由UI线程处理,而且将相应的任务交给I/O线程,它随即将该任务传递给Render进程。
- Render进程的I/O线程经过简单的解释后交给渲染线程,渲染线程接受请求,加载网页并渲染网页,这其中需要Browser进程获取资源和需要GPU进程来帮助渲染。最后Render进程将结构有I/O线程传递给Browser进程。
- Browser进程接收到结果并将结果绘制出来。
第四章 资源加载和网络栈
资源加载是一个很耗时的过程。异步执行资源(如图片、css等)的加载和执行是不会影响当前Webkit的渲染过程。同步执行的js文件会阻塞主线程的渲染过程,这会严重影响Webkit下载资源的效率;因为后面还有需要要下载的资源。这种情况下Webkit会启动另外一个线程去遍历后面的HTML网页,收集需要的资源URL,然后发送请求,这样可以避免被阻塞。与此同时,Webkit能够并发下载这些资源,甚至并发下载js代码,这种机制对于网页的加载提速是很明显的。
渲染引擎、js引擎、js加载三者是互斥的?至少前两者是的。
由于安全(Render进程是没有权限去获取资源的)和效率上的考虑,Render进程的资源获取实际上是通过进程间通信将任务交给Browser进程来完成,Browser进程有权限从网络和本地获取资源。
Chroumium的本地缓存包括一个索引文件和四个数据文件(如果缓存比较大,那么是一个数据文件)。
SDPY协议是HTTP2的基础,它的核心思想是多路复用,仅使用一个连接链传输一个网页中的众多资源:
- 利用一个TCP连接传输不限个数的资源请求,减少了TCP连接的维护成本。HTTP1.1版本里,一个TCP请求里所有的数据是按照顺序进行的,服务器处理完上一个请求才会处理下一个请求,这样如果前面的请求慢,容易造成后面请求的排队,这也就是所谓队头阻塞。SDPY里可同时发送多个请求,而且不用按照顺序一一对应,避免了请求的阻塞。
- 根据资源请求的特性和优先级,调整这些资源请求的优先级。
- 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送。
- 引入新的压缩技术(一方面使用gzip或compress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号)
第五章 HTML解释器和DOM模型
HTML解释器的流程:字节流(bytes)->字符流(characters)->词语(token)->Xss验证(可选)->节点->DOM树。 DOM树的创建只能在渲染线程上创建和访问,从字符串到词语这个阶段可以交给单独的线程来做。
当渲染引擎接收到一个事件的时候,它会通过HitTest(Webkit中一种检查触发事件在哪个区域的算法)检查哪个元素是直接的事件目标。
影子(Shadow)DOM:如<vedio>标签,其内部功能是很复杂的,但是对外只暴漏一个html标签;相当于对节点内部封装,外部看到的有限,但是内部逻辑是很复杂的。它主要解决了一个文档中可能需要大量交互的多个DOM树建立和维护各自功能边界的问题。 createShadowRoot是js中提供的创建影子DOM的方法。
第六章 CSS解释器和样式布局
CSS的样式规则、选择器(标签、类型、ID、属性、后代、子女、相邻同胞)、盒模型、包含块(Containing Block)模型、样式属性(背景、文本、字体、列表、表格、定位)。
CSSOM:CSS对象模型。它的思想是在DOM中的一些节点接口中加入获取和操作CSS属性或者接口的js接口
布局计算是一个递归的过程,这是因为一个节点的大小通常需要计算它的子女节点的位置、大小等信息。当首次加载、viewport大小改变、动画以及通过js改变样式信息时都会触发重新计算布局。
第七章 渲染基础
Webkit的布局计算使用RenderObject树并保存计算结果到RenderObject树中,RenderObject树同其他树(如:RenderLayer树)构成Webkit渲染的主要基础设施。
为一个DOM树节点创建RenderObject对象的规则:
- DOM书中的document节点
- DOM树中的可视节点,如html、body、div等。Webkit不会为非可视化节点(如meta标签)创建RenderObject对象
- 某些情况下Webkit需要建立匿名RenderObject节点,该节点不对应于DOM树种的任何节点,而是为了Webkit处理的需要
- RenderObject树节点和DOM树节点不是一一对应的关系
- 为RenderObject节点创建新的RenderLayer节点的规则是:(不同于css3硬件加速中的复合图层)
- document节点
- document的子女节点,也就是html节点对应的RenderBlock节点
- 显式的指定CSS位置的RenderObject节点
- 有透明效果的RenderObject节点
- 节点有溢出(overflow)、alpha或者反射等效果的RenderObject节点
- 使用Canvas 2D或 3D(webGL)技术的RenderObject节点
- Vedio节点对应的RenderObject节点
- Webkit的渲染方式主要包括三种:
- 软件渲染:绘图操作由CPU来完成
- 硬件加速渲染:绘图操作由GPU来完成
- 混合模式: 多个层的渲染结果合并到一个图像中,称之为合成渲染
硬件渲染比较适合于3D绘图。2D绘图时GPU不一定比使用CPU有优势,主要因为:1.CPU的缓存机制有效的减少了重复绘制;2.GPU资源相对CPU的内存来说比较紧张; 3. 软件渲染对待更新区域的处理可能优化到只需计算一个极小的区域,而硬件渲染可能需要重新绘制一层或则多层。
- 软件渲染结果基本上存储在CPU内存的一块区域,多数情况下是一个位图(Bitmap);存储结果会被copy到Browser的存储空间,然后通过Browser进程渲染出来。
第八章 硬件加速机制
GPU主要用来绘制3D图形,而且性能很好。GPU不能像软件渲染那样只计算其中更新的区域,需重绘所有区域;因此为了提高GPU的性能,需要对网页进行分层。分层后,部分区域的更新只在网页的一层或者几层,而不需将整个网页重绘;绘制完成后把层合成起来,即利用了GPU能力,又能减少不必要的重绘开销。
硬件加速机制在RenderLayer树建立后需要做三件事情来完成网页渲染:
- Webkit决定将哪些RenderLayer对象组合在一起,形成一个有后端存储的新层,这一新层不久后用户之后的合成(Compositing),这里称之为合成层(Compositing Layer)
- 将每个合成层包含的这些RenderLayer内容绘制在合成层的后端存储中
- 合成器将这些合成层合成起来,形成网页的最终可视化结果
- RenderLayer对象具有以下特征之一,那么它就是合成层(参考css3硬件加速中的复合图层):
- RenderLayer 具有CSS 3D属性或者 CSS 透视效果
- RenderLayer 包含的 RenderObject 节点表示的是使用硬件加速的视频解码技术的vedio元素
- RenderLayer 包含的 RenderObject 节点表示的是使用硬件加速的Canvas 2D元素或者 WebGL 技术
- RenderLayer 使用了CSS透明效果的动画或者CSS变换的动画
- RenderLayer 使用了硬件加速的 CSS FIlter 技术
- RenderLayer 使用了剪裁(clip) 或者反射(Reflection) 属性,并且它的后代中包含一个合成层
- RenderLayer 有一个Z坐标比自己小的兄弟节点,且该节点是一个合成层
硬件加速最终会调用OpenGL/OpenGLES库。GPU进程最终绘制的结果不再像软件渲染那样通过共享内存传递给Browser进程,而是直接将页面的内容绘制在浏览器的标签窗口内。
页面加载后进行绘制时,会经历计算布局、绘图和合成三个阶段,前两者耗时较多。鉴于此提升浏览器渲染性能的两者方法:
- 使用合适的网页分层技术以减少需要重新计算的布局和绘图
- 使用CSS 3D 变形和动画技术:浏览器不需要重新布局,也不需要重新绘图,只需使用合成功能,而合成功能耗时非常少。
第九章 JavaScript引擎
解释性语言(如 js)和编译型语言(如 java c++)的区别:编译确定位置、偏移信息共享以及偏移信息查找。 三者概括起来讲是因为编译型语言可以在编译的时候确定指针位置,而解释性语言只有在执行的时候才会确定。如果找js的属性只能通过属性名匹配去查找,而c++中可以根据偏移位置去直接找到。
一个js引擎要包括一下几部分:
- 编译器:将源代码编译成抽象语法树,某些引擎中还包括将抽象语法树转成字节码
- 解释器:某些引擎中,解释器主要接受字节码,解释执行这个字节码,同时也依赖垃圾回收机制
- JIT工具:(Just-In-Time技术) 它的主要思想是当解释器将源代码解释成内部表示的时候(java字节码就是一个典型的例子),js的执行环境不仅是解释这些内部表示,而且将其中的一些字节码(主要是使用效率高的部分)转成本地代码(汇编代码),这样可以被CPU直接执行,而不是解释执行,从而极大地提高性能。
- 垃圾回收器和分析工具:它们负责垃圾回收和手机引擎中的信息,帮助改善引擎的性能和功效
引擎的流程:
源代码 -> 抽象语法树 -> 字节码 -> 解释器 -> JIT -> 本地代码
v8引擎的工作原理
- 数据表示: 数据和句柄,句柄指向数据存储地址。当进行垃圾回收的时候,不需要移动数据(开销大),只需修改句柄中的指针。
- V8不会把抽象语法树转成字节码或者其他中间表示,而是通过JIT直接生成本地代码。 优点:减少了抽象语法树到字节码的转换时间。 缺点:减少了中间表示(字节码)可能的优化机会、有些场景没必要生成本地代码(过度优化)
- 优化回滚:编译器认为某些代码比较稳定,变量类型不会发生改变,然后生成高效的本地代码;如果引擎发现变量类型发生变化,需要使用一种机制将它做的这些错误决定回滚到之前的一般情况,这个过程就是优化回滚。优化回滚是一个很费时的操作,所以能够不回滚,肯定不要回滚。
var count = 0;
function ABC(){
count++;
if(count < 1000000){
return 123;
}
return new Date();
}
- 隐藏类和内嵌缓存:V8使用类和偏移位置思想,将本来需要通过字符串匹配来查找属性值的算法改进为使用类似C++编译器的偏移位置机制来实现,这就是隐藏类
function ABC(x, y){
this.x = x;
this.y = y;
}
var a = new ABC(1,1);
var b = new ABC(1,2);
- 上述例子中的a、b两个对象包含相同的属性名,因此它们被归为同一个组,也就是隐藏类,这些属性在隐藏类中有相同的偏移值。当访问这些对象的属性时,可以通过偏移值知道它们的位置并进行访问。
内嵌缓存的基本思想是将使用之前查找的结果缓存起来,也就是说V8可以将之前查找的隐藏类和偏移值保存下来。当下次查找的时候,首先比较当前对象是否也是之前的隐藏类,如果是的话,可以直接使用之前的偏移值,从而减少查找表的时间。 - 内存管理:V8采用的分代垃圾回收机制,分为年轻分代、年老分代等。
- 快照机制:快照机制就是将这些内置的对象和函数(如 Math、String、Array)加载之后的内存保存并被序列化。序列化之后的结果很容易被反序列化,经过快照机制的启动时间,可以缩减几毫秒。
JavaScriptCore和V8不同,它会生成平台无关的字节码(和java类似),然后基于此做优化,同时它的句柄不论在32位还是64位平台上,都使用64位来表示。
编写高效的JavaScript代码:
- 类型:把相同类型的元素放到一个数组中,这样引擎可以通过偏移位置来访问它们
- 数据表示:简单类型的数据直接保存在句柄中,这可以有效地减少寻址时间和内存的使用。对于数值来说,能使用整数的尽量不要使用浮点数。
- 内存:及时触发垃圾回收,可以把不再使用的对象的变量设置为空:a.x=null,或者通过delete关键字进行删除:delete a.x;但是后者有可能会由于使用了隐藏类,需要创建新的隐藏类,进而带来一些复杂的额外操作。
- 优化回滚:不要写触发优化回滚的代码
- 新机制: 如通过requestAnimationFrame替代setInterval实现动画等。
Line 63: 第8章 Android WebKit框架 157
Line 117: 第10章 WebKit的插件系统 201
atitit..主流 浏览器 js 引擎 内核 市场份额 attialx总结vOa9.doc
atitit。内部web浏览器交互方案集成总结.doc
Atitit.浏览器插件,控件的实现方式解决方案大的.doc
Atitit java集成内嵌浏览器与外嵌浏览器attilax总结.docx
Atitit.java的浏览器插件技术 Applet japplet attilax总结.doc
《webkit技术内幕》读书笔记 - 简书.html
《webkit技术内幕》读书笔记 - 简书.html