-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 コードでパーセンタイルを計算することを考えていました。

アルゴリズムが次のようになることはわかっています-

マップからすべての値を合計し、合計の 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);
        }
    }

}

誰かが見て、パーセンタイルを正しく計算しているかどうかを教えてもらえますか?

4

2 に答える 2

0

あなたの質問に対する私のコメントから:

ハッシュマップを使用しているため、キーはソートされた順序で保存されません。つまり、ループで entry.getKey() を出力すると、キーが順番に並んでいないことがわかります。それがあなたの主な問題です。TeeMap または ConcurrentSkipListMap はキーを順番に保持します

変化Map<Long, Long> histogram = new ConcurrentHashMap<Long, Long>

Map<Long, Long> histogram = new ConcurrentSkipListMap<Long, Long>()

ソートされた順序でキーを返すマップが表示されます。

コードのもう 1 つの問題は、合計を計算するときです。

total += entry.getKey() * entry.getValue(); // total += key*value

2回目の合計を計算するときは、次のことを行っています。

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 に答える