package org.jgroups.util; import java.io.DataInput; import java.io.DataOutput; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Measures min and max in addition to average * @author Bela Ban * @since 4.0, 3.6.10 */ public class AverageMinMax extends Average { protected long min=Long.MAX_VALUE, max=0; protected List<Long> values; public long min() {return min;} public long max() {return max;} public boolean usePercentiles() {return values != null;} public AverageMinMax usePercentiles(int capacity) {values=capacity > 0? new ArrayList<>(capacity) : null; return this;} public <T extends Average> T add(long num) { super.add(num); min=Math.min(min, num); max=Math.max(max, num); if(values != null) values.add(num); return (T)this; } public <T extends Average> T merge(T other) { if(other.count() == 0) return (T)this; super.merge(other); if(other instanceof AverageMinMax) { AverageMinMax o=(AverageMinMax)other; this.min=Math.min(min, o.min()); this.max=Math.max(max, o.max()); if(this.values != null) this.values.addAll(o.values); } return (T)this; } public void clear() { super.clear(); if(values != null) values.clear(); min=Long.MAX_VALUE; max=0; } public String percentiles() { if(values == null) return "n/a"; Collections.sort(values); double stddev=stddev(); return String.format("stddev: %.2f, 50: %d, 90: %d, 99: %d, 99.9: %d, 99.99: %d, 99.999: %d, 100: %d\n", stddev, p(50), p(90), p(99), p(99.9), p(99.99), p(99.999), p(100)); } protected long p(double percentile) { if(values == null) return -1; int size=values.size(); int index=(int)(size * (percentile/100.0)); return values.get(index-1); } protected double stddev() { if(values == null) return -1.0; double av=average(); int size=values.size(); double variance=values.stream().map(v -> (v - av)*(v - av)).reduce(0.0, (x, y) -> x + y) / size; return Math.sqrt(variance); } public String toString() { return count == 0? "n/a" : String.format("min/avg/max=%,d/%,.2f/%,d", min, getAverage(), max); } public void writeTo(DataOutput out) throws Exception { super.writeTo(out); Bits.writeLong(min, out); Bits.writeLong(max, out); } public void readFrom(DataInput in) throws Exception { super.readFrom(in); min=Bits.readLong(in); max=Bits.readLong(in); } }