首页 > 代码库 > MemoryCache学习

MemoryCache学习

这里(http://blog.csdn.net/wy5761/article/details/41869599)有对MemoryCache的整体介绍。本文说一说MemoryCache核心的部分。
     MemoryCache是webkit加载网页的庞大机制 -- Loader的一部分。Webkit采用了缓存机制,发起一个请求时,请求顺序经过一系列的Cache,在每层都会查找请求对应的资源是否存在,存在就返回。MemoryCache处于最上层。如果请求不在缓存,最终就会到达网络层,发起真正的网络请求,从服务器加载资源。
     MemoryCache允许占用的空间有限,而且被频繁使用,它把那些最近使用的资源都保存在内存,以加快网页访问速度。因此,替换算法对MemoryCache的影响很大。命中率是衡量MemoryCache性能的一个最主要指标。MemoryCache的实现基于LRU-SP算法,命中率一般都能达到60 - 70%。

LRU-SP
LRU是应用相当广泛的替换算法,它基于引用局部性原理,应用于大小相同的资源的效果很好。Web资源的size差异很大,从几KB到几百KB。通常,存储小的资源的收益会更大。LRU-SP算法综合考虑了资源的size、引用次数、新旧程度。目的是保留那些最近使用的、size较小的、被引用次数多的资源。它实现的方式是,根据资源的size和引用次数计算一个权值fastLog2(size/accessCount),按权值把资源分配在不同的LRUList中,处于同一个LRUList的资源权值相同。插入新的资源时,插在队头,队头的元素比队尾的优先级高。MemoryCache中是采用了一个固定大小32的LRUList Vector。根据fastLog2(size/accessCount)计算一个[0, 32)的索引,定位资源应该分配的LRUList。当一个资源的引用次数增多时,可能会更新到更高优先级的LRUList。这样管理资源的目的是有限淘汰哪些相对不重要的资源。

Prune
prune,即裁剪,也就是降低MemoryCache的内存占用。还有个evict的函数,两者是有区别的。evict会把资源从MemoryCache的内部结构中删除,被evict的资源,当要再次恢复时,就必须发起加载请求了。
     prune这个过程,首先会prune dead resource,由pruneDeadResourcesToSize函数完成。
先尝试释放资源的解码数据,如果计划完成,则返回,否则进一步evict资源。可以看到它是循环对每一个LRUList来执行这个过程的。从索引最大的LRUList开始,该LRUList存储的资源是size很大,并且引用次数少的资源。对于每一个LRUList,又是从队尾开始遍历,这样做的目的是优先淘汰哪些较久未使用的资源。
     prune dead resource 之后,接着prune live resource, 由pruneLiveResourcesToSize这个函数完成。可以看到该函数内部没有调用evict。也就是说,活动资源是不会被从MemoryCache中清除的,这一过程只是试着删除多余的数据(解码数据)。资源再次被用到时,必须重新解码,这相当于以时间换空间。

容量限制
MemoryCache原生代码限制容量为8M,这其实很大了。容量限制并不意味着,MemoryCache不会超过这个容量。它只是定义了进行Prune操作的时机,如果打开的窗口很多的时候,肯定会超过容量限制的。

数据结构
有一个map记录了所有在缓存中的资源;一个带有解码数据的活动资源列表;32个LRUList。

MemoryCache学习