From my comment on your question:
Since you are using a hash map your keys aren't going to be stored in sorted order. I.e., if you print out entry.getKey() in your loop you are going to see that the keys are not in order. So that is your main problem. A TeeMap or ConcurrentSkipListMap will keep its keys in order
changing Map<Long, Long> histogram = new ConcurrentHashMap<Long, Long>
to
Map<Long, Long> histogram = new ConcurrentSkipListMap<Long, Long>()
will give you a map that'll return your keys in sorted order.
Another issue in your code is when you calculate the total sum you do:
total += entry.getKey() * entry.getValue(); // total += key*value
and when you calculate the sum the second time around you are doing:
totalSum += CassandraTimer.histogram.get(key); // totalSum += value
I think you want to count up the total number of observations and then multiply that by 0.95. That'll give you the number of observations below the 95th percentile.
L = .95 * total_observations
Then iterate over your map, summing up the number of observations. Once the total number of observations exceeds L
then the corresponding key is the value at the 95th percentile.
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;
}
}
}