基于年纪和成本(Age & Cost)的缓存替换(cache replacement)机制
一、客户端的缓存与缓存替换机制
客户端的资源缓存:
在客户端游戏中,通常有大量的资源要处理,这些可能包括贴图、动作、模型、特效等等,这些资源往往存在着磁盘文件->内存(->显存)的数据通路,因为从磁盘文件读入内存是一个昂贵的的操作,所以很多客户端中的处理方法是放入一个缓存,当读入一个文件到内存后,就在内存中为他暂时保留一段时间,下次在读入这个文件就不用重复从磁盘读了,这种优化带来了客户端效率的极大提升,比如在一个有上百玩家的场景,可能我们用的玩家模型资源都是一个,只是贴图不同而已,如果使用缓存,那么你只需要从磁盘读取一次玩家模型的文件,而如果不使用,你可能要反复读取上百次,IO操作的低效会让用户很卡。
缓存替换:
然而我们用户的内存是有限大的,如果我们把每个资源都读进去保留而不释放,游戏就会越来越吃内存,一个典型的大象网游的资源可能几个G,最坏的情况用户读入了所有资源到缓存而不释放,那么也会因为内存不够用而崩溃。所以这里就通常要选择一些缓存替换机制:即动态的释放和加入资源到缓存,有进有出,但是要保证尽量让用户IO操作减少,一种最乐观的情况是,存在缓存中的资源恰好是用户使用的最多的资源,使用较少的会被使用多的交换出去。这模仿了CPU的cache机制。
二、现有的一些缓存替换机制:
基于CPU和操作系统的一些经典的cache replacement算法,客户端的资源缓存替换机制有以下一些做法:
1.懒人型,最简单的。就是没什么交换算法,只管读入缓存,然后只是定期的或发现缓存太大时一次性的清空缓存重来,这种在清空后会经历一段加载资源的顿卡,突然发现目前我们游戏的机制就是这样的,尴尬。。。但是这可能符合简单粗暴实用的原则。
2.LRU算发:大名鼎鼎的算法,当出现替换时,总是替换那个 上次使用时间距离限制最远的那个,这种算法认为最近使用的就是最长使用的,这种算法被多数体系结构使用,不过在某些极端情况下会导致thrash(内存的剧烈颠簸),比如说当一段时间内需要加载的东西过多时,而加载的资源呈有序重复序列时可能缓存会被一遍遍的清空。
3.MRU算法:它与LRU对应,但是它总是交换出最近使用的那个,这个倾向于保存最老的那个,听起来很奇怪,但是它往往不单独使用,通常配合LRU使用,当LRU出现thrash时转到MRU算法会有所帮助
三、基于Age和Cost 的算法:
今天看到了一种算法基于Age和Cost,似乎对客户端的缓存替换研究的更加到位一些,这种算法梗概如下:
1.Age:
为每个缓存保存一个32位的Age值初始为00000000(也就是第一次载入缓存时)(文档暂以8位代替),,每当hit一次,当前的最低位置1,每个计数区间(或每一帧)这个Age左移一位,例如某个资源在几帧内Age的变化
frame1:00000001(used)
frame2:00000011(used)
frame3:00000111(used)
frame4:00011100(not used)
frame5:00111000(not used)
根据当前的age,可以算出Age percentage Cost APC=1的数量/总的位数
APC越高说明这个资源近段时间是越有用的,替换时选择APC低的替换
基于Age的算法更加精确的得出了最近一段时间内资源的使用率,找出比lru更合理的替换,
2.Age扩展算法:
上面的每一步是按照帧来算的,实际使用中没帧来统计肯定是有点过了,可以按照一定时间片来统计,在一定时间片内可能一个资源回被用到n次,因此扩展的Age算法就单纯的标记1改为标记n,即这个统计区间内被用到的次数,如上例
time1:00000005(used 5 times)
time2:0000005A(used 9 times)
time3:000005A1(used 1 times)
time4:0005A100(not used)
time5:005A1000(not used)
这样APC=各位的值相加/最大的可能值
例如某个模型资源在上一段时间内被100个玩家引用,那么替换他的代价就明显要高很多,Age的扩展方法考虑的引用的频次
3.Age&Cost:
在实际的操作中,有些资源的替换成本是非常大的,例如从硬盘读入一个10m的贴图显然比读入一个100k的贴图成本大很多,所以替换时不能相同对待,这里考虑的成本记为relative cost(RC),算法中将最终的缓存替换成本TC=APC*RC,这样来综合考虑,通常将APC取值区间规整为0-1,而将rc规整为 1-10(算法作者认为载入文件的时间成本权重更大)。这样对不同的资源为它赋值不同的载入时间成本RC,再乘以上面的Age算法中的APC(引用频率成本),综合得出了它的缓存替换成本。一种比较简单的rc的赋值可以用它的文件大小来自动赋值。
几个例子:
APC RC TC
1 10 10 这说明这个文件的替换成本非常大,主要是文件比较大,同时它引用的频率特别高,这种资源基本上不会轻易从缓存中替换出来
0.2 8 4 这个文件很大,但是引用频率还很低,所以替换程度是中等的
1 5 5 文件很小,说明载入很快,但是引用频率很高,所以可以替换出来(因为再载入的成本低),也可以不替换出来,中等的
0.1 10 1 这个文件很大,载入很慢,但是引用很少,也就是说内存中存在一个很占地方但是几乎不怎么用的资源,值得替换出来,节省空间,因为不常用再次载入就算费时也值得
比如我们的游戏中开场有一个非常大的贴图资源,用于登录界面,它最开始有60M,(游戏中一般的贴图在几百K以下),而它在游戏中不会再被用到,现有的算法这个很大的资源会一直占在缓存里,用户内存被无故吃了很多,但是应用本算法,它的RC在游戏中可以达到上限10,但是APC基本上是下限,也许0.01,所以他的TC可能只有0.1,将登陆之后很快的时间内被从内存中释放出来。
赶紧利用这个算法节省一下我们的内存
基于年纪和成本(Age & Cost)的缓存替换(cache replacement)机制的更多相关文章
- 搜索引擎的缓存(cache)机制
什么是缓存? 在搜索领域中,所谓缓存,就是在高速内存硬件设备上为搜索引擎开辟一块存储区,来存储常见的用户查询及其结果,并采用一定的管理策略来维护缓存区内的数据.当搜索引擎再次接收到用户的查询请求时,首 ...
- HTTP请求的缓存(Cache)机制
原文地址:http://small.aiweimeng.top/index.php/archives/58.html 先来一张图: ####下面简单的来描述一下HTTP Cache机制: 当资源资源第 ...
- 一个基于STSdb和fastJson的磁盘/内存缓存
一个基于STSdb和fastJson的磁盘/内存缓存 需求 业务系统用的是数据库,数据量大,部分只读或相对稳定业务查询复杂,每次页面加载都要花耗不少时间(不讨论异步),觉得可以做一下高速缓存,譬如用n ...
- 缓存篇(Cache)~大话开篇
回到占占推荐博客索引 闲话杂淡 想写这篇文章很久了,但总是感觉内功还不太够,总觉得,要写这种编程领域里的心法(内功)的文章,需要有足够的实践,需要对具体领域非常了解,才能写出来.如今,感觉自己有写这种 ...
- 从Java视角理解CPU缓存(CPU Cache)
从Java视角理解系统结构连载, 关注我的微博(链接)了解最新动态众所周知, CPU是计算机的大脑, 它负责执行程序的指令; 内存负责存数据, 包括程序自身数据. 同样大家都知道, 内存比CPU慢很多 ...
- Kafka元数据缓存(metadata cache)
经常有人问的一个问题就是:Kafka broker到底是不是无状态的?网上有这样的说法: 正常情况下consumer会在消费完一条消息后线性增加这个offset.当然,consumer也可将offse ...
- yii中缓存(cache)详解
缓存是用于提升网站性能的一种即简单又有效的途径.通过存储相对静态的数据至缓存以备所需,我们可以省去生成这些数据的时间.在 Yii 中使用缓存主要包括配置和访问缓存组件 . 内部方法 一.缓存配置: 1 ...
- Cache replacement policies 缓存实现算法
Cache replacement policies - Wikipedia https://en.wikipedia.org/wiki/Cache_replacement_policies Cach ...
- yii中缓存(cache)详解 - 彼岸あ年華ツ
缓存是用于提升网站性能的一种即简单又有效的途径.通过存储相对静态的数据至缓存以备所需,我们可以省去生成 这些数据的时间.在 Yii 中使用缓存主要包括配置和访问缓存组件 . 内部方法 一.缓存配置: ...
随机推荐
- hdu 5062
题意:将10^0-10^6之间属于 "Beautiful Palindrome Number" 的数个数打印出来,所谓 "Beautiful Palindrome Nu ...
- svg转换工具
package com.rubekid.springmvc.utils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOu ...
- elasticsearch中的概念简述
Near Realtime(NRT) Elasticsearch接近实时.从为一个文档建立索引到可被搜索,正常情况下有1秒延迟. Cluster 一个集群有一个唯一的名字,默认是"elast ...
- Android Studio Gradle 版本不同报错解决方法
由于GFW的原因,我们在使用as时经常出现失败,或者第一次新建工程不成功. 很多博客上已经提到了如何解决第一次新建工程Gradle构建的问题,那么在打开别的工程时依旧会报错 "Failed ...
- egrep和grep有什么区别
grep默认不支持正则表达式,egrep默认支持正则表达式,egrep 等于 grep -E 命令.
- 武汉科技大学ACM:1005: 华科版C语言程序设计教程(第二版)例题5.8
Problem Description 老师给小豪出了一道题目:给你两个整数x和n(-10<=x<=10,1<=n<=10),让你求出x^1+x^2+x^3+……+x^n的结果 ...
- Qt5-控件-QMenu,QMenuBar-菜单栏详解-菜单热键-菜单校验功能
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QMenu> #inclu ...
- nodejs远程获取图片
if(require("http")) { var http = require("http"); http.g ...
- $this->success('注册成功!');
使用在控制器中,不是使用再模板中的
- javascript之闭包深入理解(二)
在上一节中,详细理解了作用域链和垃圾回收机制,似乎这两点跟闭包关系不大,但是仔细想一想就会发现,其实不然.这一节将通过上一部分的说明详细理解闭包.请看代码: function createCompar ...