您的位置:首页 > 理论基础 > 计算机网络

浏览器-09 javascript引擎和Chromium网络栈

2015-12-15 21:01 597 查看

语言的运行

C/C++语言

使用编译器直接将它们编译成本地代码(机器指令),这是由开发人员在代码编写完成之后实施;

用户只是使用这些编译好的本地代码,这些本地代码被系统的加载器加载执行,由操作系统调度CPU直接执行,无需其它额外的辅助虚拟机等;

这一过程基本上是从源代码开始,然后抽象语法树,之后中间表示,最后到本地代码;

Python等脚本语言

处理脚本语言通常的做法是开发者将写好的代码直接交给用户,用户使用脚本的解释器将脚本文件加载然后解释执行;

当然,现在Python也可以支持将脚本编译生成中间表示;

所以对于脚本语言,一般需要开发人员的编译过程;

这主要因为使用场景不一样,它的目的不是高性能;

这一过程是源代码,到抽象语法树,再到解释器解释执行;

Java语言

其可以理解为比较明显的两个阶段:

首先是像
C++
语言一样的编译器,但是,同
C++
编译器生成的本地代码结果不同,经过编译器编译之后的是字节码,字节码是平台无关的;

在运行字节码阶段,
Java
的运行环境也就是
Java
虚拟机会加载字节码,使用解释执行这些字节码;

同时现代
Java
虚拟机一般都引入了
JIT
技术,也就是前面说的将字节码转变成本地代码来提高执行效率;

这主要两个阶段,第一阶段对时间要求不严格,第二阶段则对每个步骤所花费的时间非常敏感,时间越短越好;

JavaScript语言

它是一种解释性脚本语言,但是随着众多工程师不断投入资源来提高它的速度,这使得它能够使用了
Java
虚拟机和
C++
编译器中众多的技术;

同时它的工作方式也在演变:

早期由解释器来解释它们即可,就是将源代码转变成抽象语法树,然后在抽象语法树上解释执行;

随着将
Java
虚拟机的
JIT
技术引入,现在的做法是将抽象语法树转成中间表示(也就是字节码),然后通过
JIT
技术转成本地代码,这能够大大的提高了执行效率;

当然也有些做法直接从抽象语法树生成本地代码的
JIT
技术,例如V8;

JavaScript
Java
还是有以下一些区别:

JavaScript
是无类型的语言,这使得对于对象的表示和属性的访问上比
Java
存在比较大的性能损失;

Java
语言通常是将源代码编译成字节码,这个同执行阶段是分开的,也就是从源代码到抽象语法树到字节码这段时间的长短是无所谓的,主要是尽可能的生成高效的字节码即可;而对于
JavaScript
,这些都是在网页和
JavaScript
文件下载后同执行阶段一起在网页的加载和渲染过程中来实施的,所以对它们的处理时间也有着很高的要求;

JavaScript引擎主要包括

编译器:主要工作是将源代码编译成抽象语法树,然后在某些引擎中还包含将抽象语法树转换成字节码;

解释器:在某些引擎中,解释器主要是接受字节码,解释执行这个字节码,然后也依赖来及回收机制等;

JIT
工具:一个能够能够
JIT
的工具,将字节码或者抽象语法树转换成本地代码;

垃圾回收器和分析工具:负责垃圾回收和收集引擎中的信息,帮助改善引擎的性能和功效;

JavaScriptCore引擎和V8引擎

WebKit中的JavaScript引擎

WebKit
项目中,最初只有
JavaScriptCore
引擎;在Blink还独立出来之前,为了支持不同的
JavaScript
引擎,
WebKit
设计了一套接口可以切换使用不同的
JavaScript
引擎(事实上,这一接口会降低性能),所以,
WebKit
当时可以支持两种类型的
JavaScript
引擎,那就是
JavaScriptCore
引擎和
V8
引擎;两者都是基于
WebKit
所提供的接口来同渲染引擎协同工作;

JavaScriptCore引擎

JavaScriptCore
引擎是
WebKit
中默认的引擎;

在早期阶段,性能不是特别突出;特别是,它只有解释器来解释执行JavaScript代码,这一效率十分的低效;

从2008年开始,
JavaScriptCore
引擎开始一个新的优化工作;

JavaScriptCore
最简单的处理部分,主要是将源代码翻译成抽象语法树,之后是平台无关的字节码,在最初的版本中,字节码会被
JavaScriptCore
引擎解释执行;在后面的版本中,逐渐加入了
JIT
编译器,将热点函数生成本地代码;

V8引擎

为了达到高性能的
JavaScript
代码执行效率从而获得更好的网页浏览效果,它甚至采用直接将
JavaScript
编译成本地代码的方式;

首先它也是将源代码转变成抽象语法树的,这一点同
JavaScriptCore
引擎一样,之后两个引擎开始不同;

不同于
JavaScriptCore
引擎,
V8
引擎并不将抽象语法树转变成字节码或者其它中间表示,而是通过
JIT
编译器的全代码生成器从抽象语法树直接生成本地代码,所以没有像
Java
一样的虚拟机或者字节码解释器;

这样做,主要是因为减少这抽象语法树到字节码的转换时间,这一切都在网页加载时候完成,虽然可以提高优化的可能,但是这些分析可能带来巨大的时间浪费;当然,缺点也很明显,至少包括两点:

第一是某些
JavaScript
使用场景其实使用解释器更为合适,因为没有必要生成本地代码;

第二是因为没有中间表示,会减少优化的机会因为缺少一个中间表示层;

在之后的版本中,
V8工
程师们引入了
Crankshaft
编译器,它能够对热点的
JS
函数进行生成的分析和优化后再生成本地代码,原因在于不是所有的
JavaScript
代码都合适做如此深层次的优化,因为优化本身也需要花费一定的时间;

Chromium网络栈

概述

主要作用是使用网络来下载各种类型的资源,还需要支持最新的HTML5功能
WebSockets
;

为了高效的网络机制,
Chromium
使用了预
DNS
解析和资源预取等技术,极大的减少了用户等待时间;

Chromium
又引入了
SPDY
QUIC
等新网络协议,用于减少网络传输时间;

调用栈

HTTP
协议为例,在建立
TCP
socket
连接过程中涉及的类;

首先是
URLRequest
被上层调用启动请求的时候,它会根据
URL
scheme
来决定需要创建什么类型的请求,例如
http://
file://
;还可以是自定义的
scheme
,例如
Android
系统的
file://assets/
;

URLRequest
创建的是一个
URLRequestJob
子类的一个对象,为了支持自定义的
scheme
处理方式,它是利用工厂模式;基本的思路是,用户可以在该类中注册多个工厂,当有
URLRequest
请求时候,先有工厂检查它是否需要处理该
scheme
,如果没有,继续交由下一个工厂类;最后,如果没有任何工厂能够处理的话,则交给内置的工厂来检查和处理是否是
http://
ftp://
或者
file://
等;

其次,当
URLRequestHttpJob
被创建后,它首先从
Cookie
管理器中获取跟该
URL
相关联的信息;之后,同样借助于
HttpTransactionFactory
创建一个
HttpTransaction
类的对象来表示开启一个
HTTP
连接的事务(不同于数据库中的事务概念;

HttpCache
类使用本地磁盘缓存机制,如果该请求对应的回复已经在磁盘缓存中,那么无需再建立
HttpTransaction
来发起连接,直接从磁盘中获取;

如果磁盘中没有,同时如果目前该
URL
请求对应的
HttpTransaction
已经建立,那么只要等待它的回复即可;

这些条件都不满足后,实际上才会真正创建
HttpTransaction
;

然后,
HttpNetworkTransaction
使用
HttpNetworkSession
来管理连接会话;

HttpNetworkSession
通过它的成员
HttpStreamFactory
来建立
TCP Socket
连接;

之后创建
HttpStream
对象;
HttpStreamFactory
将和网络之间的数据读写交给自己新创建的一个
HttpStream
对象来处理;

最后,是套接字的建立;
Chromium中
的跟服务器建立连接的套接字是
StreamSocket
,它是一个抽象类;同时,为了支持
SSL
机制,它还有一个子类就是
SSLSocket
;

SPDY

为了解决
HTTP
管线化技术的网络延迟和安全性问题;

使用
SPDY
协议的服务器和客户端可以将网络加载的时间减少64%;在
HTTP2.0
的草案中引入
SPDY
协议作为基础来编写;

SPDY
协议是一种新的会话层协议,它定义在
HTTP
协议和
TCP
协议之间;

协议的核心思想是多路复用,仅使用一个连接来传输一个网页中的众多资源;

它本上并没有改变
HTTP
协议,只是将
HTTP
协议头通过
SPDY
来封装和传输;

其传输方式也没有发生变化,然后使用
TCP/IP
协议;

所以,它相对比较容易的布置,服务器只需要插入
SPDY
协议的解释层,从
SPDY
的消息头中获取各个资源的
HTTP
头即可;

SPDY
协议必须建立在
SSL
层之上,这是一个比较大的限制,因为有很多网站不一定希望支持
HTTPS
;

SPDY
的工作方式有以下四个特征:

利用一个
TCP
连接来传输不限个数的资源请求的读写流,这与之前的为每个资源请求都建立一个
TCP
连接大大不同,这明显提高了
TCP
连接的利用率,减少
TCP
连接的维护成本;

根据资源请求的特性和优先级,
SPDY
可以调整它们的请求这些资源的优先级,例如对
JavaScript
资源的优先级很高,服务器优先传输回复该类型的请求;

对这些请求使用压缩技术,大大减少需要传送的字节数;这一思想已广泛应用于各种浏览器中;

当用户需要浏览某个网页的时候,支持
SPDY
协议的服务器在发送网页内容时候可以尝试发送一些信息给浏览器,告诉后面可能需要哪些资源,浏览器可以提前知道并决定是否需要下载;更极端的情况是,服务器可以主动发送资源;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: