Skip to content

Commit 3568b24

Browse files
DieBauerfstab
authored andcommitted
Remove call to Math.floor in f()
Since we can be sure that the result is always positive, rounding down is faster than using Math.floor while getting the same result. ``` Benchmark Mode Cnt Score Error Units CKMSQuantileBenchmark.ckmsQuantileF avgt 4 37,188 ± 6,681 ns/op CKMSQuantileBenchmark.ckmsQuantileF avgt 4 20,500 ± 1,054 ns/op <= Without floor() ``` Signed-off-by: Jens <[email protected]>
1 parent a3954b0 commit 3568b24

File tree

2 files changed

+59
-33
lines changed

2 files changed

+59
-33
lines changed

benchmarks/src/main/java/io/prometheus/client/CKMSQuantileBenchmark.java

Lines changed: 57 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
import org.openjdk.jmh.runner.options.Options;
99
import org.openjdk.jmh.runner.options.OptionsBuilder;
1010

11-
import java.util.*;
11+
import java.util.ArrayList;
12+
import java.util.Collections;
13+
import java.util.List;
14+
import java.util.Random;
1215
import java.util.concurrent.TimeUnit;
1316

1417
public class CKMSQuantileBenchmark {
@@ -18,79 +21,102 @@ public static class EmptyBenchmarkState {
1821
@Param({"10000", "100000", "1000000"})
1922
public int value;
2023

21-
CKMSQuantiles ckmsQuantiles;
22-
2324
List<Quantile> quantiles;
2425
Random rand = new Random(0);
2526

26-
long[] shuffle;
27+
List<Double> shuffle;
28+
29+
Quantile mean = new Quantile(0.50, 0.050);
30+
Quantile q90 = new Quantile(0.90, 0.010);
31+
Quantile q95 = new Quantile(0.95, 0.005);
32+
Quantile q99 = new Quantile(0.99, 0.001);
2733

2834
@Setup(Level.Trial)
2935
public void setup() {
3036
quantiles = new ArrayList<Quantile>();
31-
quantiles.add(new Quantile(0.50, 0.050));
32-
quantiles.add(new Quantile(0.90, 0.010));
33-
quantiles.add(new Quantile(0.95, 0.005));
34-
quantiles.add(new Quantile(0.99, 0.001));
35-
36-
37-
shuffle = new long[value];
38-
for (int i = 0; i < shuffle.length; i++) {
39-
shuffle[i] = i;
37+
quantiles.add(mean);
38+
quantiles.add(q90);
39+
quantiles.add(q95);
40+
quantiles.add(q99);
41+
42+
shuffle = new ArrayList<Double>(value);
43+
for (int i = 0; i < value; i++) {
44+
shuffle.add((double) i);
4045
}
41-
Collections.shuffle(Arrays.asList(shuffle), rand);
42-
46+
Collections.shuffle(shuffle, rand);
4347
}
4448
}
4549

4650
@Benchmark
4751
@BenchmarkMode({Mode.AverageTime})
4852
@OutputTimeUnit(TimeUnit.MILLISECONDS)
49-
public void ckmsQuantileInsertBenchmark(Blackhole blackhole, EmptyBenchmarkState state) {
53+
public void ckmsQuantileInsertBenchmark(EmptyBenchmarkState state) {
5054
CKMSQuantiles q = new CKMSQuantiles(state.quantiles.toArray(new Quantile[]{}));
51-
for (long l : state.shuffle) {
55+
for (Double l : state.shuffle) {
5256
q.insert(l);
5357
}
5458
}
5559

60+
/** prefilled benchmark, means that we already have a filled and compressed samples available */
5661
@State(Scope.Benchmark)
5762
public static class PrefilledBenchmarkState {
58-
public int value = 1000000;
63+
@Param({"10000", "100000", "1000000"})
64+
public int value;
65+
5966

6067
CKMSQuantiles ckmsQuantiles;
6168

6269
List<Quantile> quantiles;
6370
Random rand = new Random(0);
6471

65-
long[] shuffle;
72+
Quantile mean = new Quantile(0.50, 0.050);
73+
Quantile q90 = new Quantile(0.90, 0.010);
74+
Quantile q95 = new Quantile(0.95, 0.005);
75+
Quantile q99 = new Quantile(0.99, 0.001);
76+
List<Double> shuffle;
77+
78+
int rank = (int) (value * q95.quantile);
79+
6680

6781
@Setup(Level.Trial)
6882
public void setup() {
6983
quantiles = new ArrayList<Quantile>();
70-
quantiles.add(new Quantile(0.50, 0.050));
71-
quantiles.add(new Quantile(0.90, 0.010));
72-
quantiles.add(new Quantile(0.95, 0.005));
73-
quantiles.add(new Quantile(0.99, 0.001));
84+
quantiles.add(mean);
85+
quantiles.add(q90);
86+
quantiles.add(q95);
87+
quantiles.add(q99);
88+
89+
shuffle = new ArrayList<Double>(value);
90+
for (int i = 0; i < value; i++) {
91+
shuffle.add((double) i);
92+
}
93+
Collections.shuffle(shuffle, rand);
7494

7595

76-
shuffle = new long[value];
77-
for (int i = 0; i < shuffle.length; i++) {
78-
shuffle[i] = i;
79-
}
80-
Collections.shuffle(Arrays.asList(shuffle), rand);
8196
ckmsQuantiles = new CKMSQuantiles(quantiles.toArray(new Quantile[]{}));
82-
for (long l : shuffle) {
97+
for (Double l : shuffle) {
8398
ckmsQuantiles.insert(l);
8499
}
85-
100+
System.out.println("Sample size is: " + ckmsQuantiles.samples.size());
86101
}
102+
87103
}
88104

89105
@Benchmark
90106
@BenchmarkMode({Mode.AverageTime})
91107
@OutputTimeUnit(TimeUnit.NANOSECONDS)
92108
public void ckmsQuantileGetBenchmark(Blackhole blackhole, PrefilledBenchmarkState state) {
93-
blackhole.consume(state.ckmsQuantiles.get(0.95));
109+
blackhole.consume(state.ckmsQuantiles.get(state.q90.quantile));
110+
}
111+
112+
/**
113+
* benchmark for the f method.
114+
*/
115+
@Benchmark
116+
@BenchmarkMode({Mode.AverageTime})
117+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
118+
public void ckmsQuantileF(Blackhole blackhole, PrefilledBenchmarkState state) {
119+
blackhole.consume(state.ckmsQuantiles.f(state.rank));
94120
}
95121

96122
public static void main(String[] args) throws RunnerException {

simpleclient/src/main/java/io/prometheus/client/CKMSQuantiles.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,9 @@ int f(int r) {
185185
// The expected result of (2*0.01*30)/(1-0.95) is 12. The actual result is 11.99999999999999.
186186
// To avoid running into these types of error we add 0.00000000001 before rounding down.
187187
if (r >= q.quantile * n) {
188-
result = (int) Math.floor(q.v * r + 0.00000000001);
188+
result = (int) (q.v * r + 0.00000000001);
189189
} else {
190-
result = (int) Math.floor(q.u * (n - r) + 0.00000000001);
190+
result = (int) (q.u * (n - r) + 0.00000000001);
191191
}
192192
if (result < minResult) {
193193
minResult = result;

0 commit comments

Comments
 (0)