浏览器时序图&参考架构
作业要求:
一、针对一款典型浏览器,绘制浏览器处理时序图
一开始没什么头绪,参考了一位学长的博客,聊了聊发现还是所里的学长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.带有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 |
|
时序图如下
二、Edge浏览器参考架构
同样在学长的另一篇博客可以参考思路
按要求要做一个这样的参考架构(以下几个架构出自霍老师课件)
其中chrome、Mozilla和IE架构已给出
翻阅Microsoft edge的官方文档(似乎发现了新大陆),可知新版edge已经使用了chrome内核
打开电脑上的edge,用任务管理器查看进程信息(顺便看了一下chrome和firefox的信息,则不会显示这么仔细,大概是每一个标签页都作为一个完整的进程来看待)
其中主页是360导航(别骂了别骂了,没设置过这个浏览器555,就有时候看pdf挺舒服),然后新建了一个标签页搜索了”hao123”
查阅相关资料得知,老版本的Edge由MicrosoftEdge.exe
和MicrosoftEdgeCP.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 协议 ,转载请注明出处!