我正在尝试从我在95th Percentile
下方填充的数据集中计算ConcurrentHashMap
。
我有兴趣了解在第95个百分点的时间内有多少来电回来
我的地图将如下所示,它将始终按键上的升序排序 - 其中
key - means number of milliseconds
value - means number of calls that took that much milliseconds
以下是我的地图数据 -
Milliseconds Number
0 1702
1 15036
2 14262
3 13190
4 9137
5 5635
6 3742
7 2628
8 1899
9 1298
10 963
11 727
12 503
13 415
14 311
15 235
16 204
17 140
18 109
19 83
20 72
例如,从上面的数据集中,它意味着
1702次呼叫在0毫秒内恢复
15036次呼叫在1毫秒内恢复
现在,我可以通过在Excel sheet
中插入上述数据来计算第95个百分点。但我正在考虑计算Java代码中的百分位数。
我知道算法看起来像这样 -
对地图中的所有值求和,计算总和的95%,迭代地图 按升序排列的密钥保持运行的值总和,以及何时 和等于或超过先前计算的总和的95%, 关键应该是我想的第95个百分位。
下面是具有上述数据集的地图。
Map<Long, Long> histogram = new ConcurrentHashMap<Long, Long>
我不确定我的算法是否正确。我只是想知道在第95个百分点的时间里回来了多少次电话。
以下是我迄今根据上述算法得到的代码。
private static void logPercentileInfo() {
double total = 0;
for (Map.Entry<Long, Long> entry : CassandraTimer.histogram.entrySet()) {
long value = entry.getKey() * entry.getValue();
total += value;
}
double sum = 0.95*total;
double totalSum = 0;
for (Map.Entry<Long, Long> entry : CassandraTimer.histogram.entrySet()) {
totalSum += entry.getValue();
if(totalSum >= sum) {
System.out.println(entry.getKey());//this is the 95th percentile I guess
}
}
}
如果我从上述数据集中计算出第95个百分点,我是否知道一切正确。如果有任何改进,请告诉我。
更新代码: -
以下是我更新的代码,它解决了按键升序的问题
/**
* A simple method to log 95th percentile information
*/
private static void logPercentileInfo() {
double total = 0;
for (Map.Entry<Long, Long> entry : CassandraTimer.histogram.entrySet()) {
long value = entry.getKey() * entry.getValue();
total += value;
}
double sum = 0.95*total;
double totalSum = 0;
SortedSet<Long> keys = new TreeSet<Long>(CassandraTimer.histogram.keySet());
for (long key : keys) {
totalSum += CassandraTimer.histogram.get(key);
if(totalSum >= sum) {
//this is the 95th percentile I guess
System.out.println(key);
}
}
}
任何人都可以看看,让我知道我是否正确计算百分位?
答案 0 :(得分:1)
迭代ConcurrentHashMap
不会按顺序返回键。您首先需要创建一个键的排序列表,然后在后一个循环中从histogram
中提取值时迭代它。
答案 1 :(得分:0)
根据我对你问题的评论:
由于您使用的是哈希映射,因此您的密钥不会按排序顺序存储。即,如果在循环中打印出entry.getKey(),您将看到键不按顺序排列。这是你的主要问题。 TeeMap或ConcurrentSkipListMap将按顺序保持其键
更改Map<Long, Long> histogram = new ConcurrentHashMap<Long, Long>
到
Map<Long, Long> histogram = new ConcurrentSkipListMap<Long, Long>()
将为您提供一个地图,该地图将按排序顺序返回您的密钥。
代码中的另一个问题是当你计算总和时:
total += entry.getKey() * entry.getValue(); // total += key*value
当你第二次计算总和时:
totalSum += CassandraTimer.histogram.get(key); // totalSum += value
我认为您想要计算观察总数,然后将其乘以0.95。这将为您提供低于第95百分位数的观测数量。
L = .95 * total_observations
然后迭代你的地图,总结观察的数量。一旦观察总数超过L
,则相应的密钥是第95百分位的值。
private static void logPercentileInfo() {
double total = 0;
for (Map.Entry<Long, Long> entry : CassandraTimer.histogram.entrySet()) {
long value = entry.getValue();
total += value;
}
double sum = 0.95*total;
double totalSum = 0;
SortedSet<Long> keys = new TreeSet<Long>(CassandraTimer.histogram.keySet());
for (long key : keys) {
totalSum += CassandraTimer.histogram.get(key);
if(totalSum >= sum) {
System.out.println(key);
break;
}
}
}