首页 > 代码库 > MemoryCache

MemoryCache

MemoryCache模块是负责网页加载的一个庞大机制,loader的一部分。这里(https://www.webkit.org/blog/427/webkit-page-cache-i-the-basics/)可以了解更多。本文只谈Memory Cache,以及它内部的一些组件,不涉及到与loader的交互。

你可以在MemoryCache.h中找到关于MemoryCache是什么以及它的目的的简单描述。
该缓存保留网页用到的子资源:图片,js, css, 等等。它保持一个灵活但有限的dead resource窗口,窗口大小随着live resource的加载扩大/缩小。下面是一个缓存随时间增长的例子,该例子中,最小的dead resource capacity是25%, 最大的dead resource capacity是50%。
            |-----|                   Dead: -
            |----------|              Live: +
          --|----------|              Cache boundary: | (objects outside this mark have been evicted)
          --|----------++++++++++|
     -------|-----+++++++++++++++|
     -------|-----+++++++++++++++|+++++
如果shouldMakeResourcePurgeableOnEviction返回true,缓存变化的方式如下:
1 缓存中的dead resources 被保留在non-purgeable内存中
2 当我们裁剪(prune)dead resources时, 不是真的释放内存, 而是把它们的内存标记为purgeable直到内核重新申请该内存。
通过把裁剪的dead resource保留在“非纯净”常驻内存中,我们较少了因系统回收内存而不得不重新加载资源的可能性(比如当用户点击后退时)
而且通过使用purgeable memory存储无限多个资源对象,我们能够使用机器的所有内存。

purgeable/non-purgeable内存到底是什么意思呢?有的操作系统允许标记内存为可清除。意思是,从标记时刻开始,里面的内存有可能在任何时候被清除,而且不会通知应用程序。因此,当应用程序向系统请求资源时,可能被告知已被清除。这严重影响了对象的生命周期管理:
  • 这类内存不允许存储依赖于虚构函数的对象
  • 内存的所有权/引用永远不应该传给那些不把内存当做“特殊对象”的模块
  • 众所周知并广泛使用的对象生命周期管理方法(比如智能指针)不适合存储在purgeable 内存中的对象
了解了在purgeable 内存中存储对象的副作用之后,我们来看看memory cache的构成:


MemoryCache 类
这个类用于存储和管理对象的生命周期。存储的资源可能是活动的也可能是非活动的。非活动资源是指没有网页引用的资源。反之,活动资源是指至少有一个网页引用的资源。
MemoryCache client通过三个值控制对RAM的使用:
  • min dead bytes - prune时dead resources 的最小size
  • max dead bytes - prune时dead resources 的最大size
  • total capacity bytes - 活动资源和非活动资源能够使用的容量
不用惊慌。Total capacity并不决定Webkit保存在内存中的资源size上限,因此不会出现只保留加载网页一半的情况。它只是一个决定何时进行裁剪的阀值。prune又是怎么回事呢?首先,我们来解释什么是活动资源和非活动资源。当一个资源被下载时,作为raw data存储在内存(可能是图片,css, js等)。Raw data需要被解码后才能使用。资源被解码时,开始变成活动资源(意味着有CachedResourceClient需要用到它)。最后一个CachedResourceClient不在使用它时就变成非活动资源。活动资源和非活动资源都可能包含解码数据,占据着内存,这是不必要的。因此,提供了prune()方法。首先,MemoryCache将会prune非活动资源(满足dead resource size的最大最小限制),然后逐个裁剪活动资源直到所有资源的size小于total capacity。
Prune过程提供了一个机制来降低内存消耗。在文章已经提到这一古雅技术 -- purgeable memory。CachedResource能够移动存储的raw data到一个叫做PurgeableBuffer的特殊缓冲区中。Evict将会把一个资源从MemoryCache的内部结构中移除,之后恢复它的唯一方法只能是通过相应的ResourceRequest。

LRU lists
  • MemoryCache在三个结构中保持对资源的引用
  • m_resources - 一个基于LRU的map,保存了所有的在缓存中的资源
  • m_allResources - 固定大小为32的LRU列表Vector。一个资源基于访问次数被分配在合适的列表中。Prune将从最久未使用的资源开始淘汰。
  • m_liveDecodedResource - 含有解码数据的live resource。如果存储的数据超过了总的容量限制,MemoryCache将逐个删除解码数据,直到释放计划释放的空间,或者没有更多冗余数据可以释放。

原文:https://trac.webkit.org/wiki/MemoryCache#no1


MemoryCache