1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
package org.onap.music.util;
import com.google.common.math.Quantiles;
import com.google.common.math.Stats;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class ReserviorSampler {
private double[] samples;
private long length;
private int size;
public ReserviorSampler(int size) {
this.samples = new double[size];
this.size = size;
this.length = 0;
}
public void insert(double x) {
if (length < size) {
samples[(int)length] = x;
length++;
}
else {
long r = ThreadLocalRandom.current().nextLong(length);
if (r < size) {
samples[(int)r] = x;
}
}
}
public double[] getSamples() {
if (length < size)
return Arrays.copyOfRange(samples, 0, (int)length);
else
return samples;
}
}
public class SamplerHistogramTimeMeasure implements TimeMeasure
{
public static final int SAMPLER_SIZE = 1000;
private Map<String, ReserviorSampler> histograms;
private ThreadLocal<LinkedList<Pair<String, Long>>> tlContexts;
int[] p100;
public SamplerHistogramTimeMeasure() {
histograms = new HashMap<>();
tlContexts = ThreadLocal.withInitial(() -> new LinkedList<>());
p100 = IntStream.rangeClosed(0, 100)
.toArray();
}
public void init() {
tlContexts.get();
}
@Override
public void enter(String context) {
LinkedList<Pair<String, Long>> contexts = tlContexts.get();
String concatContext = (contexts.size() > 0 ? contexts.getLast().getLeft() + "." : "") + context;
contexts.add(new ImmutablePair<>(concatContext, System.nanoTime()));
}
@Override
public void exit() {
long nanoTime = System.nanoTime();
LinkedList<Pair<String, Long>> contexts = tlContexts.get();
Pair<String, Long> e = contexts.removeLast();
double t = (nanoTime - e.getRight()) * 1e-6;
ReserviorSampler h = histograms.computeIfAbsent(e.getLeft(), k -> new ReserviorSampler(SAMPLER_SIZE));
h.insert(t);
}
@Override
public Map<String, ArrayList<Double>> percentiles() {
Map<String, ArrayList<Double>> mapped = histograms.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
entry -> new ArrayList<>(new TreeMap<>(
Quantiles.percentiles().indexes(p100).compute(entry.getValue().getSamples())
).values())
));
return mapped;
}
@Override
public Map<String, Pair<Double, Double>> stats(){
Map<String, Pair<Double, Double>> mapped = histograms.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
entry -> {
Stats s = Stats.of(entry.getValue().getSamples());
if (s.count() <= SAMPLER_SIZE)
return new ImmutablePair<>(s.mean(), s.populationStandardDeviation() / 1);
else
return new ImmutablePair<>(s.mean(), s.sampleStandardDeviation() / 1);
}
));
return mapped;
}
}
|