WebKit网页加载进度算法研究(一)

来源:互联网 发布:什么是网站源码 编辑:程序博客网 时间:2024/05/22 04:04

   常用手机浏览器的人都会注意到,在加载网页时会有这样的现象:

   1. 若网页非常简单,则进度条会在开始跳几下,然后直接跳到最后

   2. 若网页非常复杂,则进度条会卡在约90%的位置很久,而加载不完。

   特别是后者造成了非常差的用户体验,因为这时候用户不知道网页是否还在加载,是否还在工作。

   这些现象都是由WebKit内部的加载进度算法造成的,该算法在ProgressTracker类中,关于这个类,这篇文章有很好的说明,这里就不再重复了。

   进度更新是由网络部分触发的,当网络部分收到一个报文,就会向上要求更新进度,并且将该报文的长度(bytesReceived) 传递上去,作为一个重要参数。

   算法其实很简单,初始值设为10%,最大值设为90%。这就是为什么打开网页后,进度会直接跳出一块,而又有很多复杂网页卡在90%的原因了。

   中间这块进度的计算是通过一个简单的数学式:

   progressValue += (maxprogressValue  - progressValue )*(bytesReceived / remainingBytes)

   progressValue 是当前进度,maxprogressValue  是最大进度,即90%。 bytesReceived 本次收到的字节数。remainingBytes剩余的总字节数,这个值是估算出来的,其估算的是否准确直接决定了算法的成败。

   此计算式虽然简单,但它保证了两件事情:

   1. 进度会一直增加,而不会出现伸缩不定的情况

   2. 不会超过最大值90%

   那么remainingBytes就很重要了,它是由(m_totalPageAndResourceBytesToLoad + estimatedBytesForPendingRequests) - m_totalBytesReceived 得到的

   m_totalBytesReceived是目前收到的总资源量,由bytesReceived累加所得,是准确值。

   m_totalPageAndResourceBytesToLoad是已经接收和正在接收的网络请求的总量,其中正在接收的值是估算值。

   但算法中有两个地方对m_totalPageAndResourceBytesToLoad值进行修正,一看算法,一目了然,这里就不多说了。

   那么最后剩下estimatedBytesForPendingRequests,它代表未开始传输的请求资源量,由progressItemDefaultEstimatedLength * numPendingOrLoadingRequests得到,即个数*大小。多么简单的小学一年级算术。。。。。progressItemDefaultEstimatedLength默认大小取为2K,这个默认值已经不是第一次遇到了。

   那么到现在为止,所有值都已经出现,有准确值也有估算值,其实这些估算值也都可以接受,唯独有一个numPendingOrLoadingRequests,未开始传输的请求个数。它错的太离谱,让人无法接受。

   numPendingOrLoadingRequests是通过遍历所有frame,累加各个frame的未处理请求数而得到的,但每个frame的未处理请求数,只有当解析到html标签时才会增加。

   由于WebKit的加载机制,一边解析一边显示,而且又有复杂javascript等情况,导致获取numPendingOrLoadingRequests的时候还有大量的html标签没有解析,所以得到的该值严重偏小。这就导致进度快速进行到接近90%,结果才发现还有一堆资源没有处理,没有办法,只有卡在那。(上层只精确到百分比的个位数,而没有小数点)

   其实numPendingOrLoadingRequests是不可能得到精确值的,总体上来看,采用这种机制已经是很好的了,但没有照顾到复杂网页的用户体验。而现在即使在移动端也有越来越多的复杂网页。所以需要在该算法的基础上进行微调,以提高加载复杂网页时的用户体验。

   


原创粉丝点击