HTML 支持的资源主要包括:HTML、JavaScript、CSS、图片、SVG、CSS Shader、视频、音频、字幕、字体、XSL样式表等算法
这些资源在 WebKit 中都有不一样的类表示,公共基类是 CachedResource
。其中 HTML文本的类型为 MainResource
,对应的资源类型叫 CachedRawResource
类。浏览器
基本思想是创建一个缓存池,优先从缓存池中读取数据。这里的所说的缓存池是内存缓存。WebKit 从资源池中查找资源的关键词是URL,只要URL不一样,就被认为是两个不一样的资源缓存
分为三种:安全
ImageLoader
属于 HTMLImageElement
CachedResourceLoader
全部特定加载器都共享它来查找并插入缓存资源,属于 HTML 文档的对象ResourceLoader
类,WebKit 须要从网络或者文件中获取资源的时候使用,只负责获取资源数据例子:有一个 “img” 元素,“src”是一个有效 URL 地址,当 HTML 解释器解析到该元素的该属性,WebKit 会建立一个 ImageLoader
对象来加载该资源,ImageLoader
建立一个缓存资源请求CachedResourceRequest
,并调用CachedResourceLoader
查找缓存资源,若是命中缓存则返回给调用者,若是没有命中则建立一个资源请求ResourceRequest
,而且调用通用资源加载器加载资源,具体到下面的 ResourceHandleInternal
,依赖于每一个 WebKit 移植的实现策略。服务器
存在默写资源会阻塞主线程渲染过程,当前的主线程渲染被阻塞时,WebKit 会启动另一个线程去遍历后面的 HTML 网页,收集须要的资源 URL,并能够并发下载这些资源。网络
资源池使用 LRU(Least Recently Used 最近最少使用)算法,而且在这个基础上添加了协商缓存。若是命中缓存,那么发送一个 HTTP 请求给服务器,说明资源在本地的一些信息,如资源更新时间,服务器根据信息判断,若是没有更新,则返回状态码 304,那么直接使用原资源;不然下载最新资源。多线程
Renderer 进程在网页的加载过程当中须要获取资源,但因为安全性(沙箱模型打开的时候,Renderer进程是没有权限获取资源的)和效率上(资源能够共享),Renderer 进程的资源获取其实是经过进程间通讯将任务交给 Browser 进程来完成。架构
WebKit 的资源加载的优化实际上是交由各个移植来实现的,WebCore 没有什么也别的基础设施,每一个移植的网络实现是很是不同的。并发
除了 HTTP 协议、DNS 解析等,还包含了 Chromium 为了减小网络时间而引入的新技术,例如 SPDY,QUIC异步
URLRequest
类被调用时,会根据 URL 的 “scheme”(协议类型,如:“http://”,“file://”等) 来决定要建立什么类型的请求,Chromium 使用工厂模式处理不一样类型的请求,例如 “http://” 类型则会使用 URLRequestJobManager
建立一个 URLRequestJob
类,具体使用哪一个工厂则是一个责任链模式,优先判断是不是用户自定义的 “scheme” 。URLRequestJob
被建立后,先从 Cookie 管理器中获取与该 URL 相关的信息,以后使用 HttpTransactionFactory
对象建立 HttpTransaction
对象开启一个 Http 链接的事务。若是请求对应的回复已经在磁盘缓存中,那么 Chromium 无需再创建 HttpTransaction
HttpNetworkTransaction
使用 HttpNetworkSession
类来管理会话。经过 HttpStreamFactory
对象来创建 TCP Socket 链接。以后 HttpStreamFactory
建立 HttpStream
对象,来处理对象和网络之间数据的读写。SteamSocket
类,它是一个抽象类,再 POSIX 系统和 Windows 系统上有不一样实现。Chromium 使用 HostResolverImpl
类来解析域名,具体调用的是 “getaddrinfo()”,是一个阻塞式函数,因此使用单独的线程处理。为了考虑效率,使用 HostCache
类来保存解析后的域名,还有 DNS 预解析机制。
要求:
实现上主要有两个类,Backend
(整个磁盘缓存) 和 Entry
(表中的表项)。至少须要一个索引文件和四个数据文件。索引文件用来索引,数据文件又称块文件。
索引文件: 包括一个索引头部和索引地址;头部用来表示该索引文件的信息(索引文件版本号、索引项数量、文件大小等信息);索引地址表保存各个表项对应的索引地址,直接将文件映射到内存地址。从内存地址能够找到数据文件,数据文件也是一个文件头加上后面的块文件,每一个块的大小是固定的,当超过 512 字节的时候会为其分配多个块。但最多不超过四个,超过一般会用单独的文件存储。若是一个表项要分配四个块,那么是和块索引位置是对齐的(起始块的位置是4的倍数)
表项结构 分为两个部分,第一部分标记本身,包括元数据信息和自身内容。另外一部分常常发生变更,主要为表项的回收算法服务,保存了回收算法所需的信息(LRU回收算法)。
一次 DNS 查询约 60~120ms,而 TCP 的三次握手也大约几十毫秒
DNS 预取:利用现有的 DNS 机制,提早解析网页中可能的链接。不是使用前面提到的 Chromium 网络栈,而是直接利用系统的域名解析机制,不会阻碍当前网络栈的工做,针对多个域名采起并行处理的方式,每一个域名的解析由一个新线程处理,结束后退出。网页开发者能够显示指定哪些域名来让 Chromium 解析,使用方法:<link rel="dns-prefetch" href='"htttp://...">
。 用户地址栏也同理。
TCP 预连接:使用追踪技术获取用户从什么网页跳转到另外一个网页,利用这些数据、和一些启发规则来 DNS 预取和 TCP 预连接,这对用户隐私是一个巨大挑战。
HTTP1.1 开始增长了管线化技术,能够将多个 HTTP 请求一次性提交给服务器,无需等待服务器回复,由于它可能将多个HTTP 请求填充在一个 TCP 数据包内。能在高延迟的连接环境下有明显的性能提高。
局限性:须要经过永久链接完成,而且只有 GET 和 HEAD 等请求能够进行管线化。
为了解决网络延迟和安全问题,根据 Google 官方数据,能够将网络加载时间减小 64%,HTTP2.0 将引入 SPDY 协议,将其做为基础来编写。
SPDY 协议是一种新的会话层协议,是一种栈式结构,被定义在 HTTP 协议和 TCP 协议之间,核心是多路复用,仅使用一个链接来传输一个网页中的众多资源。本质上并无改变 HTTP 协议,只是将 HTTP 协议头经过 SPDY 来封装传输,数据传输方式也没有发生变化。因此比较容易部署,服务器只须要插入 SPDY 协议的解释层,从 SPDY 的消息头中获取各个资源的 HTTP 头便可。但 SPDY 必须创建在 SSL 层之上。
特征:
QUIC 是一种新的网络传输协议,目标是改进 UDP 数据协议的能力,解决传输层的传输效率,并提供数据的加密,SPDY 能够在 QUIC 上工做。