我是编程方面的新手,尤其是Java。最近几个月我正在开发一个关于Web缓存算法的项目。经过大量的工作,我已经完成了所有工作(因为这是我的第一个真正的项目,我很高兴),除了一个小但重要的细节。让我更加准确。
在代码中我生成随机的Zipf分布式请求。每个请求的项目由其数字ID(reqID)区分。缓存实现为双向链表(Java LinkedList)。缓存算法称为WeightLFU,它的工作原理如下:
为每个请求分配一个由公式
给出的权重 weight = Math.pow(1/p, reqIndex);
其中p是权重因子,reqIndex是请求的数字索引(第1,第2,第3等)。
每个缓存项目的分数(我称之为加权频率,weightFreq)作为其权重之和给出。让我们看一个例子来说明这一点。假设我们有以下请求流(给出了reqID):
ReqIndex:1 | 2 | 3 | 4 |五 要求:7 | 3 | 7 | 1 | 3
假设p = 0.5(只是一个方便的值),分配给每个请求的权重是:
ReqIndex:1 | 2 | 3 | 4 |五 重量:1 | 2 | 4 | 8 | 16
因此,reqID 7的请求项目的分数是1 + 4 = 5,reqID 3的项目的分数是2 + 16 = 18,最后reqID 1项目的分数是8。
现在这就是我做错了。在这个例子中,我将得到以下结果:项目3的得分为16 + 8 + 4 + 2 + 1 = 31,项目1的得分为8 + 4 + 2 + 1 = 15等,即无论请求ID如何,代码都会对所有先前的权重进行求和。以下是代码的相关部分:
Class WeightLFU
public class WeightLFU {
//////////////////////////////////////////
// member attributes
/** weightLFU cache */
private List<Request> weightLFU = new LinkedList<Request>();
/** Max cache size */
private int M;
/** Fading factor */
private double p;
/** Weight */
private double weight;
/** Score (weightFreq) */
private double weightFreq;
/** Map of reqID (K) and weight (V) */
private Map<Integer, Double> weights;
/** Map of reqID (K) and weightFreq (V) */
private Map<Integer, Double> weightFreqs;
//////////////////////////////////////////
// member methods
// constructor, printing methods, initializers etc.
/**
* Getter for weight of request
* @param request The requested item
* @param reqIndex The index of the request
* @return this.weights.get(request.reqID) The weight of the request
*/
public double getWeight(Request request, int reqIndex) {
// calculate weight
weight = Math.pow(1/p, reqIndex);
// put request along with its weight to the weights map
weights.put(request.reqID, weight);
// return weight of requested item
return this.weights.get(request.reqID);
}
/**
* Calculate weightFreq of requested item
* @param request The requested item
* @param reqIndex Index of the request
*/
public void calcWeightFreq(Request request, int reqIndex) {
// initialize weightFreq
initWeightFreqs(request);
// calculate weight freq
weightFreq += getWeight(request, reqIndex);
// put reqID along with its weightFreq into the weightFreqs map
weightFreqs.put(request.reqID, weightFreq);
}
/**
* Getter for weightFreq of requested item
* @param request The requested item
* @return this.weightFreqs.get(request.reqID); weightFreq of req. item
*/
public double getWeightFreq(Request request) {
// return weightFreq of requested item
return this.weightFreqs.get(request.reqID);
}
// other stuff (cache lookup, insertion, replacement etc.)
}
我使用方法calcWeightFreq和另一个方法作为getter而不是将它们组合在一个getter方法中的原因只是为了避免在后面的缓存插入和替换操作中调用getter方法时使用reqIndex作为参数。这与我的问题无关。
主要课程:
// several irrelevant stuff
// scan the request list
for(int ir = 0; ir < reqs.size(); ir++) {
// assign the item in position ir in the reqs list to a Request item r
Request r = reqs.get(ir);
// other stuff
}
// other stuff
}
我明白这种异常行为是有道理的。我假设在calcWeightFreq方法中我必须扫描权重图以获得仅针对特定reqID的权重之和,但这也不起作用(我得到所有weightFreq值的0值)。
我希望我已经明确说明了这个问题。我假设它只需要5到10行额外的代码来解决,但我不知道该怎么做。任何指导将不胜感激。提前谢谢。