浏览器时序图&参考架构

作业要求:


一、针对一款典型浏览器,绘制浏览器处理时序图

一开始没什么头绪,参考了一位学长的博客,聊了聊发现还是所里的学长hhh

  • 先简单梳理一下整个网页加载过程

首先使用chrome的performance工具,我在这里访问了https://www.baidu.com/s?ie=UTF-8&wd=hao123

从点击到显示完整网页的大概时间如下

查看其call tree内容

梳理一下浏览器的渲染流程(下图出自霍老师课件)

渲染引擎是浏览器的核心部分,渲染引擎解析 HTML 文档,并将各标记逐个转化成 DOM 节点。同时也会解析外部 CSS 文件以及样式元素中的样式数据,完成HTML布局。Parser是入口点

  • DOM是文档对象模型(Document Object Model)的缩写,标准由 W3C 组织指定。

    DOM树是把 HTML 文档呈现为带有元素、属性和文本的树结构。DOM引擎解析HTML、XML、SVG、MathML、XUL等内容。

  • Render树

    包含若干带有颜色、面积等可视化属性的矩形。也就是我们学前端时的各个div的布局(从左往右、从上到下)

  • CSS解释器

    解析CSS,为DOM中的各个元素计算样式信息。

  • 脚本引擎

    包括JavaScript、VBScript、asm.js、WebAssembly等解释器,对脚本进行解释执行,并对DOM、CSS进行修改。

下图为chrome浏览器的执行流程,出自认识 V8 引擎(下文也有引用),这个图更好地说明了网页从加载内容到显示需要经过的流程

1. 对用户界面进行拖拽操作

前面操作同上,下图可以看出我是拖拽窗口了(下图为gif)

call tree显示如下:

从Call Tree可以看出对浏览器拖拽窗口主要有如下7个活动:

  • Update Layer Tree:更新页面树
  • Paint :重新绘制
  • Layout: 页面布局计算执行时触发
  • Event:resize:发生了拉伸窗口事件
  • Time Fired:定时器激活回调后触发
  • Composite Layers: Chrome的渲染引擎完成图片层合并时触发
  • Hit Test:这是跟踪指针下的对象的过程,移动屏幕上的container时会产生

用Event Log来分析,可知拉伸窗口这个动作并没有使chrome向网络栈请求资源,涉及到的只有内核部分的渲染,具体过程即上述活动依次进行

用plantUML画图,代码如下。(作图地址:https://www.planttext.com/)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@startuml
title Chrome Browser Timeline

participant Skia order 8
participant GDI order 7
participant V8 order 6
participant Blink order 5
participant Network_Stack order 4
participant Browser order 3
participant UI order 2
participant User order 1

User -> UI: enter url
UI -> Browser: make a request
Browser -> Blink : recalculate style
Blink -> GDI : draw fonts
GDI --> Blink:
Blink -> Skia : draw images
Skia --> Blink:
Blink --> Browser:page bitmap
Browser --> UI:display bitmap
UI --> User:
@enduml

时序图如下:

2.带有JavaScript脚本的HTML文档

用到js脚本的我首先想到了电商网站,于是我打开了京东官网

在Network中可以看到用到了js脚本的基本集中在前几秒

查看如下

多了一个Evaluate Script的活动,其余流程和上述基本一致。

学长的博客是这么描述整个流程的,部分可见课件(果然是我太菜了,对v8的了解还是太片面)

加载一个Javascript脚本的HTML流程:

  • 用户在UI界面输入URL
  • UI向浏览器发起请求
  • 浏览器先去找缓存里找这个页面,如果没有,就去网络栈获取URL
  • 网络栈返回页面数据
  • 浏览器将页面数据传给blink渲染引擎拿去渲染
  • blink分别依赖GDI、Skia绘制字体,图像
  • blink返回给浏览器一个页面bitmap
  • 浏览器展示bitmap到UI界面上去
  • 用户观察到页面变化

以下加一些我的补充

V8引擎在执行JavaScript的过程中,主要有两个阶段:编译和运行。与C++的执行前完全编译不同的是,JavaScript需要在用户使用时完成编译和执行。在V8中,JavaScript相关代码并非一下完成编译的,而是在某些代码需要执行时,才会进行编译,这就提高了响应时间,减少了时间开销。在V8引擎中,源代码先被解析器转变为抽象语法树(AST),然后使用JIT编译器的全代码生成器从AST直接生成本地可执行代码。这个过程不同于JAVA先生成字节码或中间表示,减少了AST到字节码的转换时间,提高了代码的执行速度。但由于缺少了转换为字节码这一中间过程,也就减少了优化代码的机会。(优化可以参考JIT是如何工作的)

V8引擎编译本地代码时使用的主要类如下所示:

  • Script:表示JavaScript代码,即包含源代码,又包含编译之后生成的本地代码,即是编译入口,又是运行入口;
  • Compiler:编译器类,辅组Script类来编译生成代码,调用解释器(Parser)来生成AST和全代码生成器,将AST转变为本地代码;
  • AstNode:抽象语法树节点类,是其他所有节点的基类,包含非常多的子类,后面会针对不同的子类生成不同的本地代码;
  • AstVisitor:抽象语法树的访问者类,主要用来遍历异构的抽象语法树;
  • FullCodeGenerator:AstVisitor类的子类,通过遍历AST来为JavaScript生成本地可执行代码。

在V8中,函数是一个基本单位,当某个JavaScript函数被调用时,V8会查找该函数是否已经生成本地代码,如果已经生成,则直接调用该函数。否则,V8引擎会生成属于该函数的本地代码。这就节约了时间,减少了处理那些使用不到的代码的时间。其次,执行编译后的代码为JavaScript构建JS对象,这需要Runtime类来辅组创建对象,并需要从Heap类分配内存。再次,借助Runtime类中的辅组函数来完成一些功能,如属性访问等。最后,将不用的空间进行标记清除和垃圾回收。

在V8中,TurboFan 和 Ignition 结合起来共同完成JavaScript的编译

用plantUML画图,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@startuml
title Chrome Browser Timeline
User -> UI: enter url
UI -> Browser: make a request
Browser -> Network_Stack:obtain a page without cache
Network_Stack -> Browser:page data
Browser -> Blink : render
Blink -> V8 :parse JavaScript scripts
V8 --> Blink :
Blink -> GDI : draw fonts
GDI --> Blink:
Blink -> Skia : draw images
Skia --> Blink:
Blink --> Browser: page bitmap
Browser --> UI: display bitmap
UI --> User:
@enduml

时序图如下

二、Edge浏览器参考架构

同样在学长的另一篇博客可以参考思路

按要求要做一个这样的参考架构(以下几个架构出自霍老师课件)

其中chrome、Mozilla和IE架构已给出

翻阅Microsoft edge的官方文档(似乎发现了新大陆),可知新版edge已经使用了chrome内核

打开电脑上的edge,用任务管理器查看进程信息(顺便看了一下chrome和firefox的信息,则不会显示这么仔细,大概是每一个标签页都作为一个完整的进程来看待)

其中主页是360导航(别骂了别骂了,没设置过这个浏览器555,就有时候看pdf挺舒服),然后新建了一个标签页搜索了”hao123”

查阅相关资料得知,老版本的Edge由MicrosoftEdge.exeMicrosoftEdgeCP.exe两个进程组成,后来的版本采用UWP架构,其进程主要由RuntimeBroker.exe和其他进程组成。其中RuntimeBroker和一些核心进程为中等完整性级别,其他进程都在AppContainer中以低完整性级别运行。

AppContainer是windows提出的进程隔离机制。通过将应用程序与不需要的资源和其他应用程序隔离,可以最大限度地减少恶意操纵的机会。

  • Browser_Broker是broker进程,负责启动C网页,同时执行类似文件保存等高特权动作,以中等完整性级别运行。
  • Runtime Broker是以中等完整性级别运行,负责权限管理。
  • Chakra JIT Complier是JavaScript的编译器,负责解析和执行Javascript代码。
  • User Interface Service顾名思义是提供用户接口服务。
  • Background Tab Tool 是标签页工具。
  • 360导航和hao123_360搜索是我打开的页面。Edge会为每一个标签页创建一个进程,是浏览器sandbox机制的体现。
  • Microsoft Edge Mangaer是主要进程,有待进一步分析。

其实大部分内容是还是和上述chrome的结果相似的

查看MicrosoftEdgeCP.exe的dll,根据描述,推测:

  • EdgeContent.dll是Edge的浏览器引擎
  • edgehtml.dll是渲染引擎
  • JS解释器:chakra.dll
  • XML解释器:xmllite.dll
  • 网络相关组件包含
    • windows HTTP服务:winhttp.dll
    • Win32的Internet扩展:wininet.dll
    • Web客户端DLL:Windows.Web.dll
  • 用户界面后端包含
    • Windows DirectUI 引擎:dui70.dll
    • Windows Direct User Engine:duser.dll
    • DirectX Graphics Infrastructure:dxgi.dll

结合以上信息,可以初步绘制Edge参考架构:


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!