-1

我正在尝试根据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. 但我正在考虑计算 Java 代码中的百分位数。

我知道算法看起来像这样-

对 map 中的所有值求和,计算总和的 95%,按升序迭代 map 键,保持值的运行总和,当 sum 等于或超过先前计算的总和的 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);
        }
    }

}

谁能看一下,让我知道我是否正确计算了百分位数?

4

2 回答 2

1

迭代 aConcurrentHashMap不会按顺序返回键。您首先需要创建一个排序的键列表,然后在从histogram后一个循环中提取值时对其进行迭代。

于 2013-04-22T02:05:37.943 回答
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;
        }
    }
}
于 2013-04-22T02:08:55.863 回答