我模拟Web缓存替换算法。 我可以为那些以串行方式到达缓存对象缓存和L型的请求的申请N个对象。
请求的对象可以通过INT字段REQID(从0数字ID多达N-1)来区分。 我不得不重写等于能够比较请求对象。
我实现了使用阵列的高速缓存 - 一种简单,朴素,静态数组。
缓存充满类型请求的对象,并具有最大尺寸M:
/** Max cache size */
private int M;
/** Cache */
private Request[] cache = new Request[M];
我有插入,驱逐和缓存中的对象的替代品。
我也曾经作为ArrayDeque实施的最后K请求的滑动窗口:
/** Max window size */
private int K;
/** Window */
private Deque<Request> window = new ArrayDeque<Request>(K);
值M和K在构造函数初始化,并在主要设置()。
我一直在一个HashMap对象的得分(在最后K请求的滑动窗口请求数):
/** Map of reqID (K) - Score (V) */
Map<Integer, Integer> score;
我守在缓存项的得分方面下令缓存,得分最高的是在左端和最低分是在右端。
由于这样的事实,当我有一个高速缓存命中一个项目的分数增加1分而当我有一个项目的请求从窗口该项目的分数减少1下降,在这种情况下,我可能有缓存有关项目在缓存中的下一个项目在其左侧或分别交换位置正确,重新排序。 所以,我应该能够知道在每个缓存(随机)项的指数在任何给定的时间。 为此,我使用所谓的反整型字段和一个HashMap叫的位置:
/** Counter = position in the cache */
private int counter;
/** Map of ReqID (K) - Counter (V) */
private Map<Integer, Integer> positions;
最后,我用一个inCache地图,以避免“for循环”,在查找操作:
/** Map with boolean flags to check whether an item (ReqID) is in cache or not */
private Map<Integer, Boolean> inCache;
和isMoreThanOne标志,以避免调用当前缓存大小,吸气时,这个尺寸较大:
/** Flag for more than 1 items in cache */
private boolean isMoreThanOne;
其原因是,由于我的高速缓存是香草阵列而不是一个ArrayList,它不具有一个大小()方法,和长度字段是给定的,而不是当前的高速缓存大小的固定容量。 因此,为了得到当前高速缓存大小,我应该做到以下几点(因为我不是100%,如果它是正确的,请看看):
/**
* Getter for current cache size
* @return Current cache size
*/
public int getCacheSize() {
// temp counter
int count = 0;
// scan the cache
for(int i = 0; i < this.cache.length; i++) {
// as long as the items are not null
if(this.cache[i] != null) {
// increase the counter by 1
count += 1;
}
// when the first null item found
else {
// jump out of the loop
break;
}
}
// return the current cache size (counter)
return count;
}
那长而neccessary介绍后,这里是缓存插入,我得到一个ArrayIndexOutOfBoundsException的代码:
/**
* Cache insertion operation
* @param request The requested item that is inserted into the cache
*/
public void doCacheInsert(Request request) {
// if this is the first item inserted into the cache
if(getCacheSize() == 0) {
// set counter
counter = M-1;
// insert item at index counter
this.cache[counter] = request; // HERE I HAVE THE MESSAGE
// put position index into positions list
this.positions.put(request.reqID, counter);
}
// if this is not the first item inserted into the cache
else {
//if the cache has not reached its max size
if(getCacheSize() != this.cacheWindowLFU.length) {
// decrease counter by 1
counter -= 1;
// insert item at index counter
this.cache[counter] = request;
// put position index into positions list
this.positions.put(request.reqID, counter);
// set isMoreThanOne flag
isMoreThanOne = true;
}
// if the cache has reached its max size
else {
// reset counter to M-1
counter = M-1;
// insert item at index counter
this.cache[counter] = request;
}
}
// activate flag for item in inCache map
this.inCache.put(request.reqID, true);
}
我得到的消息几乎就在该方法的开始,在第1,如果在该行块:
// insert item at index counter
this.cache[counter] = request;
......我真的不知道为什么!
编辑:这是我的构造函数:
/**
* Constructor
* @param M Max cache size
* @param K Max window size
* @param N Number of items
*/
public Algorithm(int M, int K, int N) {
// initialize max cache size and max window size
this.M = M;
this.K = K;
// initialize counter
counter = 0;
// initialize isMoreThanOne flag
isMoreThanOne = false;
// allocate inCache, winFreqs, and positions maps
inCache = new HashMap<Integer, Boolean>(N);
scores = new HashMap<Integer, Integer>(N);
positions = new HashMap<Integer, Integer>(N);
}
这里是主要的相关部分(),这是主类中:
// stuff..... (e.g. # of sim runs etc.)
// number of items
int numItems = 20;
// number of requests
int numR = 40;
// maximum cache size
int M = 5;
// maximum window size
int K = 3;
// stuff...... (e.g. generation of requests, start of statistics etc.)
// instantianate object of type Algorithm
Algorithm alg = new Algorithm(M, K, numItems);
// stuff..... (e.g. lookup, insertion, replacement, # of hits, hit rate etc.)