/*
* Copyright (c) 2013-2015 Chris Newland.
* Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD
* Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki
*/
package org.adoptopenjdk.jitwatch.histo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class Histo
{
private Map<Long, Integer> bucketMap = new HashMap<>();
// lots of writes, not COWAL
private List<Long> values = new ArrayList<>();
private long lastTime = 0;
private int maxCount = 0;
private long resolution = 1;
public Histo()
{
}
public Histo(long resolution)
{
this.resolution = resolution;
}
public void addValue(long inValue)
{
long value = inValue;
synchronized (values)
{
values.add(value);
}
if (resolution > 1)
{
value = (value / resolution) * resolution;
}
int newCount = 0;
if (bucketMap.containsKey(value))
{
newCount = bucketMap.get(value) + 1;
}
else
{
newCount = 1;
}
bucketMap.put(value, newCount);
if (newCount > maxCount)
{
maxCount = newCount;
}
if (value > lastTime)
{
lastTime = value;
}
}
public void clear()
{
bucketMap.clear();
lastTime = 0;
maxCount = 0;
}
public List<Map.Entry<Long, Integer>> getSortedData()
{
List<Map.Entry<Long, Integer>> result = new ArrayList<>(bucketMap.entrySet());
Collections.sort(result, new Comparator<Map.Entry<Long, Integer>>()
{
@Override
public int compare(Entry<Long, Integer> o1, Entry<Long, Integer> o2)
{
return o1.getValue().compareTo(o2.getValue());
}
});
return result;
}
/*
* Nearest rank percentile calculation from
* http://en.wikipedia.org/wiki/Percentile
*/
public long getPercentile(double percentile)
{
long result = 0;
List<Long> valuesCopy = null;
synchronized (values)
{
valuesCopy = new ArrayList<>(values);
}
Collections.sort(valuesCopy);
int count = valuesCopy.size();
if (percentile >= 100)
{
result = valuesCopy.get(count - 1);
}
else if (percentile <= 0)
{
result = 0;
}
else
{
double position = 0.5 + (percentile) / 100.0 * count;
int index = (int) Math.round(position) - 1;
result = valuesCopy.get(index);
}
return result;
}
public long getLastTime()
{
return lastTime;
}
public int getMaxCount()
{
return maxCount;
}
}