4

我正在尝试测量每个线程插入数据库所需的时间。我已经在ConcurrentHashMap命名映射中捕获了所有这些性能数字,例如每个线程插入的时间。在那个并发哈希映射中,它将是这样的。

Key- 10
Value- 2

这意味着 2 个呼叫在 10 毫秒内返回。下面的另一个例子

Key - 20
Value -1

这意味着,1 个呼叫在 20 毫秒内返回。

而且该地图将包含更多数据,这意味着更多的键值对。

所以现在我正在尝试通过使用上面的相同地图来做类似下面的事情,这意味着我需要迭代上面的地图以获得该特定范围内的以下数字。那有可能吗?

How many calls(X number) came back in between 1 and 20 ms
How many calls(X number) came back in between 20 and 40 ms
How many calls(X number) came back in between 40 and 60 ms
How many calls(X number) came back in between 60 and 80 ms
How many calls(X number) came back in between 80 and 100 ms
How many calls(X number) came back after 100 ms

我最初想到的一些代码。

SortedSet<Long> keys = new TreeSet<Long>(map.keySet());
for (Long key : keys) {
    System.out.print(key + " : ");
    for (int i = 0; i < map.get(key); i++) {
                 // Not sure what I am supposed to do here?
    }
    System.out.println();
}

有人能帮我一下吗?

更新:-

我的地图样本值-

{31=3, 48=1, 33=1, 30=12, 43=1, 38=1, 32=1}

这意味着总调用是3+1+1+12+1+1+1 = 20通过valuemap

除此之外,我需要弄清楚上述情况意味着这样的事情

How many calls(X number) came back in between 1 and 20 ms
How many calls(X number) came back in between 20 and 40 ms
How many calls(X number) came back in between 40 and 60 ms
How many calls(X number) came back in between 60 and 80 ms
How many calls(X number) came back in between 80 and 100 ms
How many calls(X number) came back after 100 ms

以下是我尝试使用以下建议的代码-

私人静态无效drawHistogram(地图地图){

int counter[] = new int[6];

for (Integer key : map.keySet()) {
    System.out.println("" + key);    

    // add sample
    int idx = key / 20;
    idx = Math.min(idx, counter.length - 1);
    counter[idx]++;
    }

for (int i = 0; i < counter.length; i++) {
    System.out.println(counter[i] + " came back in between " + i * 20 + " and " + (i + 1) * 20
            + " ms");
}

}

如您所见,我打了 20 个电话,但这仅显示 7 个电话。我做错了什么吗?这是我得到的输出-

0 came back in between 0 and 20 ms
5 came back in between 20 and 40 ms
2 came back in between 40 and 60 ms
0 came back in between 60 and 80 ms
0 came back in between 80 and 100 ms
0 came back in between 100 and 120 ms

仅显示 7 个电话。但是有20个电话。

4

5 回答 5

0
SortedSet<Long> keys = new TreeSet<Long>(map.keySet());
Map<Long, Long> values = new HashMap<Long, Long>();
Integer total = null;
Integer current = null;
Long point = null;
for (Long key : keys) {
    System.out.print(key + " : ");
    current = map.get(key);
    if(key >= 1 && key <= 20) {
        point = 1;
    } // Do Other Comparisons also and change point 2, 3, 4, 5, 6

    total = values.get(point);
    if(total == null) {
        total = 0;
    }
    total += current;
    values.put(point, total);
    System.out.println();
}

现在如果你循环keySet抛出values

第 1 点将是How many calls(X number) came back in between 1 and 20 ms

于 2013-02-08T06:08:18.747 回答
0

您可以使用 aNavigableMap来查询一系列数字(头、尾)。线程安全的实现是ConcurrentSkipListMap.

特别看方法NavigableMap<K,V> headMap(K toKey, boolean inclusive)NavigableMap<K,V> tailMap(K fromKey, boolean inclusive)SortedMap<K,V> subMap(K fromKey, K toKey)

例子

//your existing concurrent map changed to concurrent navigable map
NavigableMap<Long, Long> throughputCounter = new ConcurrentSkipListMap<Long, Long>();
            // this prints for inclusive values - 1 and 20 are both included
            System.out.println("How many calls(X number) came back in between 1 and 20 ms:" + calcThroughput(throughputCounter.subMap(1L, true, 20L, true)));
            System.out.println("How many calls(X number) came back in between 20 and 40 ms:" + calcThroughput(throughputCounter.subMap(20L, true, 40L, true)));
            System.out.println("How many calls(X number) came back in between 40 and 60 ms:" + calcThroughput(throughputCounter.subMap(40L, true, 60L, true)));
            System.out.println("How many calls(X number) came back in between 60 and 80 ms:" + calcThroughput(throughputCounter.subMap(60L, true, 80L, true)));
            System.out.println("How many calls(X number) came back in between 80 and 100 ms:" + calcThroughput(throughputCounter.subMap(80L, true, 100L, true)));
            System.out.println("How many calls(X number) came back in after 100 ms:" + calcThroughput(throughputCounter.tailMap(100L)));

    private Long calcThroughput(NavigableMap<Long, Long> subMap) {
        Long sumOfARange = new Long(0);
        for (Long value : subMap.values()) {
            sumOfARange += value;
        }
        return sumOfARange;
    }
于 2013-02-08T06:09:44.150 回答
0

你根本不需要地图。您可以简单地将时间除以 20 (ms) 并在数组中增加一个计数器。

public static void main( String[] args) {
    int counter[] = new int[6];
    for ( int i = 0 ; i < 100 ; i++ ) {
        int time = (int) ( Math.random() * 200 );
        System.out.println( "" + time  );
        // add sample
        int idx = time / 20;
        idx = Math.min( idx, counter.length-1);
        counter[idx]++;
    }

    for ( int i = 0 ; i < counter.length ; i++ ) {
        System.out.println( counter[i] + " came back in between " + i*20 + " and " + (i+1)*20 + " ms" );
    }
}

请注意,最后一个数组元素保存所有样本的数量> = 100ms,因此应该更正输出。省略以使代码尽可能简短和清晰。

示例输出

13 came back in between 0 and 20 ms
10 came back in between 20 and 40 ms
13 came back in between 40 and 60 ms
10 came back in between 60 and 80 ms
11 came back in between 80 and 100 ms
43 came back in between 100 and 120 ms

更新:输出应该是

for ( int i = 0 ; i < counter.length-1 ; i++ ) {
    System.out.println( counter[i] + " came back in between " + i*20 + " and " + (i+1)*20 + " ms" );
}
System.out.println( counter[counter.length-1] + " came back after 100" ms" );
于 2013-02-08T06:22:14.513 回答
0

你可以试试:

SortedSet<Long> keys = new TreeSet<Long>(map.keySet());

int group1To20=0;
int group20To40=0;
int group40To60=0;
int group60To80=0;
int group80To100=0;
int groupAbove100=0;
for (Long key : keys) {
 if(key>=0 && key<=20){
  group1To20=group1To20+map.get(key);
  }elseif(key>20 && key<=40){
   group20To40=group20To40+map.get(key);
  }
 //Similarly do as above for other range of group

}//end of loop


System.out.print("group 1-20 contains " +  group1To20);
//Now print the group range and values here

}

我已经尝试过您的解决方案。我可能误解了你的问题。如果是这样,请为我澄清这个问题。

于 2013-02-08T06:23:36.760 回答
0

预计需要轻松重新定义存储桶大小(实际上是您聚合到的存储桶数量),我建议:

    Map<Integer, Integer> values = new HashMap<Integer, Integer>();

    int[] definition = {0, 20, 40, 60, 80, 100};
    int[] buckets = new int[definition.length];

    for (int time : values.keySet()) {
        for (int i=definition.length-1; i>=0; i--) {
            if (time >= definition[i]) {
                buckets[i] += values.get(time);
                break;
            }
        }
    }
    for (int i=0; i<definition.length; i++) {
        String period = "";
        if (i == definition.length-1) {
            period = "greater than " + definition[i] + "ms";
        } else {
            period = "between " +
                      (definition[i]+1) +
                      " and " +
                      definition[i+1] + "ms";
        }
        System.out.println(buckets[i] + " came back " + period);
    }

可配置性是通过更改来管理的definition。我使用以下代码对此进行了测试:

    Random rnd = new Random();
    for (int i=0; i<1000; i++) {
        int time = rnd.nextInt(121);
        Integer calls = values.get(time);
        if (calls == null) {
            calls = Integer.valueOf(0);
        }
        calls += 1;
        values.put(time, calls);
    }
于 2013-02-08T06:52:00.753 回答