【读书笔记】【WebKit技术内 幕(三)】GPU硬件加速渲染、canvas与WebGL、 JavaScript与JavaScript 引擎、JavaScriptCore与V8

前言

上接:

Something great

  • parser: 解析器
  • AST :(Abstract Syntax Tree,抽象语法树)
  • openGL :(Open Graphics Library,开放图形库);一个大部分平台都支持的 底层图形库的 API 标准
  • DirectX:(Direct eXtension,简称DX)微软的多媒体API。
  • 沙箱(sandBox):操作系统对 进程的可访问的内存地址所做的限制。
    • 渲染进程被 Sandbox 隔离,网页 web 代码内容必须通过 IPC 通道才能与浏览器内核进程通信,通信过程会进行安全的检查。
    • 沙箱运行:渲染器在单独的进程中运行,通过沙箱限制其对系统资源(文件、网络、显示、击键)的访问,而须通过父浏览器进程访问
  • 插件:浏览器的插件用于显示网页特定内容
  • 扩展:浏览器的扩展用于增加浏览器新功能的软件或压缩包
  • inspector:(web inspector,调试页面))
  • DOM:(Document Object Model,文档对象模型)
  • XSS(cross site security)
  • CSS:(cascading style sheet,级联样式表)
  • OpenGL ES:(OpenGL for Embedded Systems)是 OpenGL 三维图形API的子集
  • WebGL:(Web Graphics Library)是一种3D绘图协议。
  • 图形上下文:所有的绘图都由图形上下文(graphics context,GC)来完成。
    • 表示的是图形绘制的平台。包含绘制参数以及需要执行一系列绘图命令的设备信息。图形上下文定义了包括绘制颜色、裁剪区域、曲线宽度以及绘制模式信息、文本字体信息、一些合成选项或者是一些其他的有关绘制的基本属性。
  • < canvas >:是H5中最受欢迎的元素,在页面上划出一片区域,利用JS在上面画出图形,起初由Apple公司提出,各大浏览器厂商也对其做了不同程度上的实现。
    • canvas中规定了了2D context和3D context(WebGL),目前绝大部分浏览器支持2D context。WebGL的发展还比较缓慢。
  • WebGL:一套基于3D图形定义的JS接口。
  • Skia 图形库:2D向量图形处理函数库,包含字型、坐标转换,以及点阵图都有高效能且简洁的表现。

第8章 硬件加速机制

硬件加速基础 —— ***
  • 硬件加速:
    • 这里的硬件加速就是使用GPU 硬件能力帮助渲染网页。 主要用于绘制3D图形。
      • 对于GPPU绘图:
        • 不像软件渲染:只是计算其中更新区域。
        • 当更新时,如果没有分层,引擎可能需要重新绘制所有区域。因为计算更新部分对GPU来说可能更费时间。 (因为CPU和GPU,一个是通用计算,一个是专用计算)(GPU更适合大规模并发计算
          • 当分层后,部分更新只在几个层,只需要重新绘制那几个层,并将其和之前绘制完的层合成,使用了GPU的能力,也减少了重绘开销。
      • 为了减少GPU内存使用,硬件加速机制在RenderLayer 树建立之后,做三件事情完成网页渲染:
        • webkit 决定哪些 RenderLayer 对象组合,形成一个有后端存储的新层,新层不久后用于合成,称其为合成层。
          • 一个RenderLayer 对象没有后端存储的新层,那么就使用它父亲使用的合成层。
        • 每个合成层包含的RenderLayer 内容绘制在合成层的后端存储中
        • 合成器用于将多个合成层合成起来,形成网页最终可是结果:图片。
          • 合成器 是一种能将多个合成层,按照前后顺序、合成层的3D变形等设置而合成一个图像的设施。
  • WebKit硬件加速设施 :
    • 一个 RenderLayer 对象需要后端存储时,创建一个RenderLayerBacking 对象,负责RenderLayer 对象的各种存储。
      • 如果一个 RenderLayer 对象被webkit 创建了后端存储,那么该RenderLayer 被称为合成层。
      • 每个合成层有一个 RenderLayerBacking ,负责管理RenderLayer 所需所有后端存储。
    • 为何要合成层:
      • 合并一些 RenderLayer 层,减少内存使用。
      • 合并后,减少合并带来的重绘性能和处理上的困难。
      • 单独层能显著提升性能的,不会减少性能。
      • 在这里插入图片描述
        • GraphicsLayer 表示 RenderLayer 前景层、背景层需要的一个后端存储。
      • 在这里插入图片描述
      • 由RenderLayerCompositor 管理这些合成层,其需要计算和决定哪些RenderLayer 对象是合成层,并未合成层创建GraphicsLayer对象。
  • 硬件渲染过程:
    • 软件渲染中,paintLayer 函数被递归调用,从RenderLayer 根节点开始,直到所有RenderLayer 对象都被遍历为止。
      • 硬件加速机制中,加入了合成层,每个RenderLayer 对象被绘制到祖先链中最近的合成层。
      • 最后一个步骤:渲染引擎将所有绘制完的合成层合成起来,由webkit 的移植来做。

在这里插入图片描述

  • 3D图形上下文:
    • webkit 中的 3D图形上下文 主要是提供一组抽象接口,提供类似OpenGLES 的功能。用于使用OpenGL绘制3D图形的能力。
      • 这一层抽象,将webkit 各个移植不同部分隐藏,webcore 可以使用统一接口。
      • webkit 中,3D图形上下文 主要用途是WebGL。
    • webkit 的GraphicsContext3D 类,是个抽象类,包含的接口所处理的对象是OpenGL中所提供的能力,如 针对纹理、着色器、纹理贴图、顶点等GL操作。
      • GraphicsContext3D 接口三种类型:
        1. 所有移植共享实现的接口
        2. 一些移植能够共享实现的接口,可以直接调用OpenGL等。
        3. 跟每个移植相关。
Chromium的硬件加速机制 —— ***
  • GraphicsLayer的支持 :

    • GraphicsLayer 对象是对一个渲染后端存储某层的抽象。,webkit 移植中需要具体实现类支持功能。
    • * 这个过程是各种映射,目的是:**将webkit 的合成层,映射到合成器中的合成层。** * Blink 中就不需要这么多层次,因为Blink 仅被chromium 使用。
  • 框架:

    • chromium中,GPU进程负责所有GPU硬件加速操作。
      • 包括GPU硬件的绘图和合成。
        • 每个网页的 renderer进程,将3D绘图和合成操作通过IPC传递给GPU进程,由其统一调度执行。
        • android 中,没有GPU进程,是Browser进程中的GPU线程。
      • Browser 进程也和GPU进程通信,用于创建GPU进程、提供网页渲染最后绘制的目标存储。
        • GPU 进程同样提供3D图形能力接口给Pepper 插件使用。
    • WebKit 渲染引擎对GPU的使用:
      • WebKit 定义了两种类型图形上下文。都可以使用GPU加速,加速机制最后都是调用OpenGL/OpenGLES库。

      • 在这里插入图片描述

      • chromium中的3D、2D图形上下文对应:3D图形上下文实现、Skia画布(canvas)。

        • 他们调用(GL操作)之后被转换为IPC消息,传递GPU进程,通过解释器解释后,调用GL函数指针表中函数,这些函数指针是从GL库中获取。
          • windwos下3D图形库是D3D,不是OpenGL接口,chromium使用通过ANGLE使用D3D来封装成OpenGL方式的接口。
          • 在这里插入图片描述
      • chromium 快进程的硬件加速机制工作,GPU进程和renderer进程需要同步命令。

        • 因为renderer进程需要等待GPU进程做好某些操作后才继续执行。(如?)
        • GPU进程处理一些命令后,会报告当前状态,renderer进程检查状态和自己的期望来确定是否满足。
        • GPU进程最终绘制结果不再像 软件渲染 那样通过 共享内存 传递给Browser进程,而是直接将页面内容 绘制在浏览器的标签窗口内。
  • 命令缓冲区 :

    • 命令缓冲区(command buffer)主要用于GPU进程和GPU的调用进程 传递GL操作命令。
      • chromium 使用共享内存,采用环形缓冲区的方式实现,采用基于GLES编码。
        • 命令被分为命令头和命令体。命令头:长度+标识、命令体:立即操作数等。
        • 长命令,采用桶(bucket)机制:共享内存的分块传输,最后合并到接收端的桶中。
  • Chromium合成器(Chromium Compositor):

    • 架构:
      • 合成器:将多个合成层合成,并输出一个最终结果。即合成网页划分后的合成层。
        • 输入为多个合成层,每层都有一些属性(3D变换等)。输出为一个后端存储,如一个GPU的纹理缓冲区。
        • 可以合成网页、用户界面、标签页。
      • 合成器采用:表示和实现分离
        • webkit 对合成层的各种设置,最后都使用Layer 树表示,每个Layer树包含3D变形、裁剪等属性。
        • 但是chromium 将这些属性应用到后端存储并合成,委托LayerImpl 树来完成。
        • 通过代理 协调和同步两者之间的这些操作。
      • 表示部分和实现部分,不同线程中,为线程化合成。在一个线程中,就是线程内合成。
        • android 中还存在合成器在Browser 进程中,用于将网页结果和浏览器用户界面结合。
    • 基础设施:
      • 为了支持chromium 的线程化合成和线程内合成,引入很多类来支持他们
        • 包括了 事件处理部分、合成层的表示和实现、合成层组成两种类型的树、合成调度器、合成器的输出结果、各种后端存储等资源、支持动画和3D变形所需的基础设施。 这些一起构成了chromium 合成器。
      • 代理是个抽象类,定义了Layer 树和LayerImpl树之前完成合成所需的转接工作。
      • 在这里插入图片描述
      • 在这里插入图片描述
    • 瓦片话的后端存储:
      • 和分层一样,减少成本,提高性能。
        • GPU硬件支持有限的纹理大小
        • 瓦片话存储,一部分变化,只需要重绘存在更新的瓦片。
        • 层滚动时,大小相同的后端存储容易被重复利用。
    • 线程化合成模式才需要调度器。
    • 合成过程: 由调度器调度。
      1. 创建输出结果的目标对象 Surface ,也就是合成结果的存储空间
      2. 计算一个新的帧,包括计算滚动和缩放大小、动画计算、重新计算网页的布局、绘制每个合成层等。
      3. 将Layer 树 中包含这些变动同步到LayerImpl树中。
      4. 合成LayerImpl树中各个层并交换前后帧缓冲区,完成一帧的绘制和显示动作。
      • 步骤1 在最开始时调用,后面网页出现动画护着JS代码修改CSS样式和DOM等情况,一般只执行后三个步骤或者最后一个步骤。
  • 减少重绘:

    • 重绘包括:计算布局、绘图、合成。合成耗时较短。
      • webkit 减少重绘:
        • 使用合适的网页分层技术,减少需要重新计算的布局和绘图。(层次化canvas 渲染优化技术)
        • 使用CSS 3D变化和动画技术
          • CSS 3D 变形技术,让浏览器仅使用合成器来合成所有的层就可以达到动画效果。
          • 计算每一帧时, JS代码首先设置元素3D属性、设置样式信息,chrome 只需要在随后使用合成功能。
其他硬件加速模块
  • 2D图形的硬件加速机制:

    • 传统很多绘图操作都是针对2D图形,如边框、文字、图片、填充
      • HTML5引入2D绘图的画布功能,提供2D绘图的JS 接口使用JS代码来绘制2D图形。
      • 2D绘图本身是使用2D图形上下文,一般使用软件方式绘制,也就是光栅化。
        • 2D绘图也可以使用GPU,即3D绘图来完成。称为2D图形的硬件加速机制。
      • 当前2D图形的硬件加速应用于:网页基本元素的绘制、以及HTML5新元素 **canvas,**用于绘制2D图形。
  • 2D图形上下文:

    • 2D图形上下文 在webkit 的chromium 移植使用Skia 图形库完成2D图形操作。
    • 在这里插入图片描述
      • chromium 创建一个Skia 图形库中提供的SkCanvas 对象处理 Webkit 的2D图形操作请求 。
        • 使用软件绘图还是GPU绘图,取决于SkCanvas 对象的设置。
        • SkCanvas 类表示一个画布,2D图形操作在这个画布上处理,绘制结果也保存在SkCanvas 对象中。
          • 当软件绘制时,使用光栅扫描的方法一一计算绘制像素结果,使用的是CPU内存,保存的是一个个像素值,如RBGA格式。
          • GPU硬件来绘图,需要传入SkSurface_Gpu 对象。将2D图形操作转变成对GL的操作,使用GrContext的3D图形上下文绘制,存储在GPU的内存缓冲区。
  • canvas 2D:

    • canvas 开始时只是个2D画布对象,用JS接口在画布上绘制任意2D图形。

      • 后来提出在该元素上用JS绘制3D图形,即WebGL或者canvas 3D。
    • canvas 的getContext 指定创建上下文对象的类型为2d返回一个2D图形上下文,提供绘制2D图形的各种应用程序编程接口。(如圆形、文字、图形变换、图片绘制及合成等)

    • canvas 2D可以使用软件绘图,也可以使用GPU来加速绘图。

      • 网页的canvas 2D 技术同样需要借助Skia 技术。
        * 在这里插入图片描述
        • DOM树构建后,webkit 检查有无变化的CSS样式时,JS代码改变了canvas 元素属性,webkit 才会更新RenderObject 树和RenderLayer 树。
      • 绘图时,chromium采用缓存模式处理JS代码的2D图形操作。
        • chromium 绘制新帧时,Skia 图形库才会一次性提交并绘制缓存的操作。
      • canvas 2D 机制由JS代码绘制2D图形,所以这时候的canvas 所在合成层已经绘制完成,这时候webkit 不需要绘制该层,只需要改变3D图形上下文的状态。
      • chromium 采用的延迟思想,合并了很多2D绘图操作,提高了绘制的性能。
  • WebGL:

    • 3D图形上下文: webcore 表示该上下文的抽象是 GraphicsContext3D。
    • WebGL的实现:
      • WebGL 是一套基于3D图形定义的JS接口,基于canvas,可以使用3D图形接口绘制各种3D图形。
        • WebGL 被执行的每个GL调用直接传给GPU进程,没有缓存机制。
  • CSS 3D变形:

    • CSS 3D变形和动画是HTML5 的新特性,CSS 3D变形用于对任意DOM子树做3D变形。
      • WebGL是在一个canvas 元素内部绘制3D图形,CSS 3D变形可以对任何元素进行3D变形, 是可以被元素子女继承的属性。
    • webkit 对应用变形技术的DOM子树使用单独合成层、硬件加速机制。
      • 当JS代码修改元素变换属性值时,最后样式是设置在该合成层上,合成过程中,webkit 通过3D变形作用到该合成层上。
      • 仅在第一次绘制元素内容,之后仅设置变换属性值,然后重新合成即可。

第9章 JavaScript引擎

JavaScript & JavaScript 引擎 & 渲染引擎
  • JS 是脚本语言,主要用于Web 客户端,为了控制网页客户端的逻辑,如同用户交互、异步通信等。
    • 是一种解释型语言( 最然后面不一样了),函数为第一等公民,可以被当参数或返回值来传递。
    • JS是一种无类型语言: (动态类型语言)
      • C++、JAVA,都是静态类型语言、强类型语言,编译时能确定每个变量类型。
        • 事先已经知道所存取的成员变量类型,语言解释系统只需要利用数组和位移来存取这些变量和方法的地址。
      • JS在运行时计算和决定类型。 根据实际传递的对象来计算。
        • 对应变量为属性名-属性 对,这些属性名也会被存储(一般是字符串),访问时需要通过属性名匹配来获取相应的属性。
        • 在执行阶段可以修改对象的属性(添加或删除属性本身)
    • JIT(just - in - time) 技术:
      • 为了提高JS运行速度,解决解释性语言的性能问题。
        • 让JS执行环境,不仅仅解释这些内部表示,而将其中一些字节码转成本地代码(汇编),直接被CPU执行, 而不是解释执行。
        • java虚拟机、javascriptcore、v8 都有使用 JIT。
    • 作用域链和闭包:
      • 闭包:是一个拥有许多变量和绑定了这些变量的环境的表达式(如函数),因而这些变量也是该表达式的一部分)
      • js使用作用域链实现闭包,作用域链由执行环境维护,JS中所有标识符都通过作用域链查找值。
        • JS代码运行时,预先创建了一个全局的域,该域包含一个全局上下文, 包含了winddows、navigatoe 等内置对象。
        • 在这里插入图片描述
        • 进入函数时,执行环境为其创建一个上下文,指向其父上下文, 形成一个作用域链。
          • 查找变量时,函数上下文中没有包含该变量,那么执行环境会不停向上查找。
        • 右侧代码使用了匿名函数:
          • 因为JS 全局函数在其他.js 文件中也可见,容易导致名字冲突和模块化问题。
          • 匿名函数不会污染全局空间,同时内部函数根据作用域链,只在该匿名函数内有效,不会影响其他代码,这里使用的就是闭包技术。
  • JavaScript引擎:
    • JS 引擎:将JS代码处理并执行的运行环境。
      • C/C++ :编译器编译成本地代码,被系统加载器加载执行,这些本地代码由OS调度CPU直接执行。
      • Python 等解释型脚本语言:使用脚本解释器,将脚本加载后解释执行。
      • java:经过编译器生成字节码, 字节码与平台无关,java 运行环境是java虚拟机,加载字节码使用解释器执行字节码。也引入JIT,将字节码变成本地代码提高执行效率。
      • JavaScript:通常啊转换为AST解释执行,也有使用JIT技术提高执行效率。
        • js 编译和执行分不开,在网页的加载和渲染过程中实施,对其处理时间有很高要求。
  • 在这里插入图片描述
    • JS引擎包括:
      • 编译器:编译为抽象语法树或字节码。
      • 解释器:解释执行字节码,依赖垃圾回收机制。
      • JIT工具:字节码转换为本地代码,依赖垃圾回收机制、
      • 垃圾回收器和分析工具:负责垃圾回收、手机引擎信息。
  • JavaScript引擎和渲染引擎 :
  • js引擎提供接口给渲染引擎,让其处理JS代码。
  • 渲染引擎根据桥接接口让JS访问DOM。
  • 在这里插入图片描述
V8引擎 —— *
  • 采用直接将JS编译成本地代码的方式。Node.js 就是基于V8。

    • V8,只是个C++库而已。
    • 代码结构:
    • 在这里插入图片描述
    • 接口使用:
      • 在这里插入图片描述
      • V8,只是个C++库而已。
      • V8提供的D8工具,通过V8接口实现一个可执行程序,可以读入JS文件输出结果,提供调试JS的基础能力。
  • 工作原理:

    • V8中数据表示分为:内容和句柄。
      • 句柄大小固定,存着指向数据的指针。
        • 因为V8需要垃圾回收, 也需要移动数据内容,修改指针更简单,且使用的句柄还没变化。
        • 存整数的话,就是高31位表示。对于其他类型,用高30位存指针,低2bits 存01 标识是地址。
          • 因为存放都是4字节对齐,地址的低两位是00就可。
          • 在这里插入图片描述
    • V8工作过程:
      • 编译+运行,且有延迟思想,让有些代码的编译在运行时才发生,减少有些代码不会运行到的时间开销。
      • 缺点:直接从AST到本地代码,无法从中间代码进行优化。
      • 代码编译:
        • 在这里插入图片描述
        • parser:生成AST。
        • FullCodeGenerator:生成本地代码。
    • FullCodeGenerator因为本地代码和硬件平台相关,所以使用多个后端生成实际代码。
      • 在这里插入图片描述
      • 代码运行:
        • 在这里插入图片描述
        • 延迟编译:函数调用时,查找本地代码是否生成,没生成就触发生成。减少有些代码不会运行到的时间开销。
        • 在这里插入图片描述
    • 优化回滚:
      • 编译器认为代码稳定,变量类型不变,生成高效的本地代码。
      • 发现一些变量类型变化,就熬回滚之前的一般情况。
    • 隐藏类和内存缓存:
      • 参考C++,为JS对象构建类型信息,将原本的 通过字符串匹配来查找属性值 ->替换为使用C++编译器类似的 偏移地址机制实现。
        • 将相似属性的对象,抽象出来一个类,但是类型变化后,就要将变化的对象重新抽象一个类
    • 内存管理:
      • 包括内存划分和JS垃圾回收。
        • 在这里插入图片描述
    • 快照:
      • 将内置对象和函数加载后的内存,保存并序列化,序列化的结果很好反序列化,减少启动时间。
  • 绑定和扩展

    • V8提供扩展:通过V8提供的基类Extension,扩展JS能力。
    • 绑定:使用IDL文件、接口文件生成绑定文件,同V8引擎代码一起编译。
JavaScriptCore引擎
  • JavaScriptCore 最开始主要基于抽象语法树的解释器,后来重新实现了编译器、字节码解释器。后来将内嵌缓存、基于正则表达式的JIT 和简单的JIS引入。

    • 代码结构:

      • 在这里插入图片描述
    • 数据表示:

      • 同样使用句柄,用64标识,除了小整数外,直接可以存浮点类型。但是句柄占用空间较大。
  • 模块:

    • JavaScriptCore 使用了字节码的中间表示。加入了多层JIT编译器帮助改善性能。
      • 因为有了字节码,就不需要JS源代码了。
      • 在这里插入图片描述
  • 内存管理:

    • 像V8一样,引入了分代垃圾回收机制。
  • 绑定: JavaScriptCore同样提供绑定机制,渲染引擎同样通过该机制访问DOM的操作函数。

实践——高效的JavaScript代码
  • 编程方式:在这里插入图片描述

第10章 插件和JavaScript扩展

参考

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值