webkit技术内幕读书笔记 (四)
资源缓存
资源缓存的目的是为了提高资源使用的效率,其基本思想是建立一个资源的缓存池,当需要请求资源的时候先去资源池查找是否有相应的资源,如果没有则向服务器发送请求,webkit收到资源后将其设置到该资源类的对象中去,以便于缓存后下次使用,webkit从资源池中查找资源的关键字是URL,URL标记了资源的唯一性。
以上说明一个问题,如果ulr不同,就算内容相同也会被重新请求。
资源加载
鉴于从网络获取资源时一个非常耗时的过程,通常一些资源的加载是异步执行的,也就是说资源的获取和加载不会阻碍 当前 WebKit的渲染过程,例如图片、CSS文件。当然,网页也存在某些特别的资源会阻碍主线程的渲染过程,例如 JavaScript 代码文件。这会严重影响 WebKit 下载资源的效率,因为后面可能还有许多需要下载的资源,WebKit会怎么做?因为主线程被阻碍了,后面的解析工作没办法继续往下进行,所以对于 HTML 网页中后面使用的资源也没有办法知道并发送下载请求。当遇到这种情况的时候,WebKit的做法是这样的:当前的主线程被阻碍时。WebKit会启动另外一个线程去遍历后面的HTML页面,收集需要的资源URL,然后发送请求,这样就可以避免被阻碍。与此同时,WebKit 能够并发下载这些资源,甚至并发下载 JavaScript 代码资源。
为了验证以上是否正确,在本地搭了个服务器测试,其中有一个index.html页面,和一个服务器脚本,服务器脚本用来延迟加载js。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h2>h2</h2>
<script src="http://localhost:8081/index.js"></script>
<h3>h3</h3>
<img src="test/images/0.png" alt="">
<img src="test/images/1.png" alt="">
<img src="test/images/2.png" alt="">
<script src="index.js"></script>
<script>
console.log("ok");
</script>
</body>
</html>
nodejs脚本 index.js
var http = require("http");
http.createServer(function(req,res){
}).listen(8081);
index.html请求了8081端口的一个js脚本,但是我始终不给它响应。

可以看到加载js的那一块始终是一个pending状态,但是在js后面的资源还是被下载了,也就是说webkit确实是开了多个线程去下载资源的,但你也可以看到,它虽然是开了多个线程去下载资源,但是并没有去执行后面的代码,如下图

从另外一个方面也可以看出它没有去执行后面的代码,我在index.html中写了这么一段代码<script src="index.js"></script>假如说它执行了,那么应该报错才对,因为这段代码的内容就是那个nodejs中的,如果我返回内容,效果就是下面这样

也就是说,虽然资源webkit可能开多个线程去下载,但是执行代码,始终用的是一个线程,对于执行javascript代码使用一个线程执行,还算好理解,因为某些js文件可能依赖于其他的js文件,如果说使用多线程,这必然是一个比较麻烦的问题,另外如果某些js文件必须早于其他文件执行,那么多线程依然还是个问题,对于图片和dom大概也是同样的道理吧,如果说下载下来的图片,马上就去显示,那如果说我在前面的js中给body加了一个display:none;那么你说是这个图片是显示呢还是不显示呢?不能因为前面的js堵塞了后面的代码执行,你就乱显示吧,这也是多线程了一些烦恼吧。
资源的生命周期
同CachedResourceLoader对象一样,资源池也属于HTML文档对象,由于资源池不能无限大,因此要用相应的机制来替换其中的资源,从而加入新的资源,这种机制采用的算法为LRU(最近最少使用)算法。对于打开网页刷新当前页面的场景,对于某些资源,webkit需要直接重新发送请求,要求服务器端将内容重新发送过来,但对于大多数资源,Webkit则可以利用HTTP协议减少网络负载,在HTTP协议中对此有规定,游览器可以发送消息确认是否需要更新,如果有则游览器重新获取该资源,否则就需要利用该资源。
webkit的做法如下,首先判断资源是否在资源池中,如果在则发送一个HTTP请求给服务器,说明该资源在本地的一些信息,例如修改时间等,服务器根据该信息进行判断,如果没有更新则返回状态码304表示不需要更新,直接利用资源池中的资源,否则webkit申请下载最新的资源内容。
DNS预取和TCP预连接
一次DNS查询的平均时间大概在60~120ms之间或者更长,而TCP的三次握手时间大概也是几十毫秒或者更长,看似是一个很短的时间,但是相对于网页的渲染来说,这是一个相当长的时间,如何有效的缩短这段时间,Chromium给出了自己的解决方案—DNS预取和TCP预连接。
首先讲一下DNS预取,他的主要思想就是利用现有的DNS机制,提前解析网页中可能的网络连接。具体来说,就是当用户正在浏览当前网页的时候,Chromium提取网页中的超链接,将域名抽取出来,利用比较少的CPU和网络带宽来解析这部分域名或IP地址,这样一来,用户根本感觉不到这一过程。但是当用户单击这些链接的时候,由于已经提前做好了DNS解析,可以节省不少时间,特别是对于域名解析比较慢的时候,效果尤其明显。(DNS预取技术针对多个域名采取并行处理的方式,每个域名的解析均是由新开启的一个线程来处理的,结束后此线程即退出)
当然,我们也可以显式指定预取哪些域名来让Chromium解析,这非常直接了当。特别是对于那些需要重定向的域名,具体做法如下:
<link rel="dns-prefetch" href="http://this-is-a-dns-prefetch-example.com">。DNS预取技术不仅应用于网页中的超链接,当我们在地址栏中输入地址后,候选项同输入的地址很匹配的时候,在我们敲下回车键获取该网页之前,Chromium已经开始使用DNS预取技术解析该域名了。
接下来是TCP预连接,Chromium使用追踪技术来获取用户从什么网页跳转到另外一个网页,可以利用这些数据,一些启发式的规则和其他暗示来预测用户下面回单击什么超链接,当有足够的把握的时候,他便会DNS预取,更进一步,还可以预先简历TCP连接。听起来是不是特别6?不错,Chromium就是这么6!同DNS预取技术一样,追踪技术不仅应用于网页中的超链接,当用户在地址栏中输入地址的时候,也同样适用!
webkit技术内幕读书笔记 (四)的更多相关文章
- webkit技术内幕读书笔记 (一)
本文部分摘录自互联网. Chromeium与Chrome Chromium是Google为发展自家的浏览器Google Chrome而打开的项目,所以Chromium相当于Google Chrome的 ...
- webkit技术内幕读书笔记 (二、三)
可视区和网页 通常网页比屏幕的可视区面积要大,因此当网页内容在可视区中放不下时,一般浏览器会提供滚动条. 从URL到构建完DOM树的过程 当用户输入网页URL的时候,WebKit调用其资源加载器加载该 ...
- 深入理解linux网络技术内幕读书笔记(四)--通知链
Table of Contents 1 概述 2 定义链 3 链注册 4 链上的通知事件 5 网络子系统的通知链 5.1 包裹函数 5.2 范例 6 测试实例 概述 [注意] 通知链只在内核子系统之间 ...
- Struts2技术内幕 读书笔记三 表示层的困惑
表示层能有什么疑惑?很简单,我们暂时忘记所有的框架,就写一个注册的servlet来看看. index.jsp <form id="form1" name="form ...
- Struts2技术内幕 读书笔记一 框架的本质
本读书笔记系列,主要针对陆舟所著<<Struts2技术内幕 深入解析Strtus2架构设计与实现原理>>一书.笔记中所用的图片若无特殊说明,就都取自书中,特此声明. 什么是框架 ...
- 深入理解linux网络技术内幕读书笔记(三)--用户空间与内核的接口
Table of Contents 1 概论 1.1 procfs (/proc 文件系统) 1.1.1 编程接口 1.2 sysctl (/proc/sys目录) 1.2.1 编程接口 1.3 sy ...
- Kafka技术内幕 读书笔记之(四) 新消费者——消费者提交偏移量
消费组发生再平衡时分区会被分配给新的消费者,为了保证新消费者能够从分区的上一次消费位置继续拉取并处理消息,每个消费者需要将分区的消费进度,定时地同步给消费组对应的协调者节点 .新AP I为客户端提供了 ...
- Kafka技术内幕 读书笔记之(四) 新消费者——心跳任务
消费者拉取数据是在拉取器中完成的,发送心跳是在消费者的协调者上完成的,但并不是说拉取器和消费者的协调者就没有关联关系 . “消费者的协调者”的作用是确保客户端的消费者和服务端的协调者之间的正常通信,如 ...
- Kafka技术内幕 读书笔记之(四) 新消费者——新消费者客户端(二)
消费者拉取消息 消费者创建拉取请求的准备工作,和生产者创建生产请求的准备工作类似,它们都必须和分区的主副本交互.一个生产者写入的分区和消费者分配的分区都可能有多个,同时多个分区的主副本有可能在同一个节 ...
随机推荐
- Java理论学时第二节。课后作业。
枚举不属于原始数据类型,它的每个具体值都引用一个特定的对象,相同的值则引用同一个对象. 可以使用“==”和equals()方法直接比对枚举变量的值,换句话说,对于枚举类型的变量,“==”和equals ...
- docker mac
官网上有安装方法.已安装成功. 容器千万不能随便删 现在已经不用boot2docker,使用dockertools来安装docker,dockertools中包含docker-machine,等等. ...
- SRM481
250pt 题意:上帝知道一个“先有鸡还是先有蛋”的答案,上帝和N<=10^6个人说了答案,不过有x个人故意告诉了他们错误的答案,然后有一个人问了这N个人问题的答案,有M个人说先有鸡,N-M个人 ...
- UNIGUI上传文件
UNIGUI上传文件 uniGUI提供了一个文件上传控件TUniFileUpload,进行数据的导入就变得比较容易.首先将TUniFileUpload控件放置在窗体上,按下导入按钮后,执行TUniFi ...
- 微信WeixinJSBridge API使用实例
http://www.jb51.net/article/66642.htm 这篇文章主要介绍了微信WeixinJSBridge API使用实例,本文直接给出HTML代码,代码中包含了很多实用功能,如图 ...
- hdu 1.2.7
#include<cstdio> #include<iostream> using namespace std; int main() { //freopen("in ...
- Power BI Embedded 与 Bot Framework 结合的AI报表系统
最近最热门的话题莫过于AI了,之前我做过一片讲 BOTFRAMEWORK和微信 相结合的帖子 如何将 Microsoft Bot Framework 链接至微信公共号 我想今天基于这个题目扩展一下,P ...
- Apache中 RewriteCond 规则参数介绍
RewriteCond指令定义了规则生效的条件,即在一个RewriteRule指令之前可以有一个或多个RewriteCond指令.条件之后的重写规则仅在当前URI与Pattern匹配并且满足此处的条件 ...
- Python 高级编程——单例模式
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. 在 Py ...
- Asp.Net MVC记住用户登录信息 下次登录无需输入密码
有的时候做网站,就需要记住用户登录信息,下次再登录网站时,不用重复输入用户名和密码,原理是浏览器的cookie把状态给记住了! 那么具体是怎么实现的呢?下面博主将一部分代码贴出来,想要完整版的Demo ...