LRU算法

来源:互联网 发布:python range函数菜鸟 编辑:程序博客网 时间:2024/05/22 15:02

最近为游戏里纹理占用的内存做个控制,让它限定在某个值内,用的是cocos(2.x很老的版本)的引擎,虽然里面的纹理缓存池( CCTextureCache ) 有个接口 removeUnusedTexture 可以释放不使用的纹理 ( 引用计数==1 ),但是如果频繁需要打开的ui的纹理也会被释放掉。这不够理想,所以需要一套类似lru的算法来管理纹理对象,释放最不常用的纹理,达到内存即可限定在某个值内,又不会释放频繁使用的纹理对象。模拟的代码在这里 git。 
在作为cocos 的插件嵌入到cocos中,还有点问题在调试中。 
lru算法思想可以参照一下内容


LRU是Least Recently Used 近期最少使用算法。内存管理的一种页面置换算法,对于在内存中但又不用的数据快(内存块)叫做LRU,Oracle会根据那些数据属于LRU而将其移出内存而腾出空间来加载另外的数据,一般用于大数据处理的时候很少使用的数据那么就直接请求数据库,如果经常请求的数据就直接在缓存里面读取。

最近最久未使用(LRU)的页面置换算法,是根据页面调入内存后的使用情况进行决策的。由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU置换算法是选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间t,当须淘汰一个页面时,选择现有页面中其t值最大的,即最近最久未使用的页面予以淘汰(可以使用这种方法去实现)。

LRU的实现

1) 可利用一个栈来保存当前使用的各个页面的页面号。每当进程访问某页面时,便将该页面的页面号从栈中移出,将它压入栈顶。因此,栈顶始终是最新被访问页面的编号,而栈底则是最近最久未使用页面的页面号。(由于效率过低在leetCode上超时,代码未贴出)

2) 也可以过双向链表和HashMap来实现。

双向链表用于存储数据结点,并且它是按照结点最近被使用的时间来存储的。 如果一个结点被访问了, 我们有理由相信它在接下来的一段时间被访问的概率要大于其它结点。于是, 我们把它放到双向链表的头部。当我们往双向链表里插入一个结点, 我们也有可能很快就会使用到它,同样把它插入到头部。 我们使用这种方式不断地调整着双向链表,链表尾部的结点自然也就是最近一段时间, 最久没有使用到的结点。那么,当我们的Cache满了, 需要替换掉的就是双向链表中最后的那个结点(不是尾结点,头尾结点不存储实际内容)。

如下是双向链表示意图,注意头尾结点不存储实际内容:

1头 --> 结 --> 结 --> 结 --> 尾
2结     点     点     点     结
3点 <-- 1  <-- 2 <-- 3  <-- 点

假如上图Cache已满了,我们要替换的就是结点3。

哈希表的作用是什么呢?如果没有哈希表,我们要访问某个结点,就需要顺序地一个个找, 时间复杂度是O(n)。使用哈希表可以让我们在O(1)的时间找到想要访问的结点, 或者返回未找到。


假定现有一进程所访问的页面序列为:

4,7,0,7,1,0,1,2,1,2,6

随着进程的访问,栈中页面号的变化情况如图所示。在访问页面6时发生了缺页,此时页面4是最近最久未被访问的页,应将它置换出去。

28151727-5c27ca2146414bbe889397fcfc855863


0 0
原创粉丝点击