Skip to content

Commit e574a9d

Browse files
Better control over setting string formats for the benchmark metrics (#461)
1 parent aeeffa0 commit e574a9d

File tree

6 files changed

+148
-60
lines changed

6 files changed

+148
-60
lines changed

jvector-examples/src/main/java/io/github/jbellis/jvector/example/Grid.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -377,10 +377,10 @@ private static void testConfiguration(ConfiguredSystem cs,
377377
System.out.format("Using %s:%n", cs.index);
378378
// 1) Select benchmarks to run
379379
List<QueryBenchmark> benchmarks = List.of(
380-
new ThroughputBenchmark(2, 0.1),
381-
new LatencyBenchmark(),
382-
new CountBenchmark(),
383-
new AccuracyBenchmark()
380+
ThroughputBenchmark.createDefault(2, 0.1),
381+
LatencyBenchmark.createDefault(),
382+
CountBenchmark.createDefault(),
383+
AccuracyBenchmark.createDefault()
384384
);
385385
QueryTester tester = new QueryTester(benchmarks);
386386

jvector-examples/src/main/java/io/github/jbellis/jvector/example/benchmarks/AccuracyBenchmark.java

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,33 +29,46 @@
2929
* Measures average recall and/or the mean average precision.
3030
*/
3131
public class AccuracyBenchmark extends AbstractQueryBenchmark {
32-
static private final String DEFAULT_FORMAT = ".2f";
32+
private static final String DEFAULT_FORMAT = ".2f";
3333

34-
private final boolean computeRecall;
35-
private final boolean computeMAP;
36-
private final String formatRecall;
37-
private final String formatMAP;
34+
private boolean computeRecall;
35+
private boolean computeMAP;
36+
private String formatRecall;
37+
private String formatMAP;
3838

39-
public AccuracyBenchmark(boolean computeRecall, boolean computeMAP, String formatRecall, String formatMAP) {
40-
if (!(computeRecall || computeMAP)) {
41-
throw new IllegalArgumentException("At least one parameter must be set to true");
42-
}
39+
public static AccuracyBenchmark createDefault() {
40+
return new AccuracyBenchmark(true, false, DEFAULT_FORMAT, DEFAULT_FORMAT);
41+
}
42+
43+
public static AccuracyBenchmark createEmpty() {
44+
return new AccuracyBenchmark(false, false, DEFAULT_FORMAT, DEFAULT_FORMAT);
45+
}
46+
47+
private AccuracyBenchmark(boolean computeRecall, boolean computeMAP, String formatRecall, String formatMAP) {
4348
this.computeRecall = computeRecall;
4449
this.computeMAP = computeMAP;
4550
this.formatRecall = formatRecall;
4651
this.formatMAP = formatMAP;
4752
}
4853

49-
public AccuracyBenchmark() {
50-
this(true, false, DEFAULT_FORMAT, DEFAULT_FORMAT);
54+
public AccuracyBenchmark displayRecall() {
55+
return displayRecall(DEFAULT_FORMAT);
5156
}
5257

53-
public AccuracyBenchmark(String formatRecall) {
54-
this(true, false, formatRecall, DEFAULT_FORMAT);
58+
public AccuracyBenchmark displayRecall(String format) {
59+
this.computeRecall = true;
60+
this.formatRecall = format;
61+
return this;
5562
}
5663

57-
public AccuracyBenchmark(String formatRecall, String formatMAP) {
58-
this(true, true, formatRecall, formatMAP);
64+
public AccuracyBenchmark displayMAP() {
65+
return displayMAP(DEFAULT_FORMAT);
66+
}
67+
68+
public AccuracyBenchmark displayMAP(String format) {
69+
this.computeMAP = true;
70+
this.formatMAP = format;
71+
return this;
5972
}
6073

6174
@Override
@@ -71,6 +84,10 @@ public List<Metric> runBenchmark(
7184
boolean usePruning,
7285
int queryRuns) {
7386

87+
if (!(computeRecall || computeMAP)) {
88+
throw new RuntimeException("At least one metric must be displayed");
89+
}
90+
7491
int totalQueries = cs.getDataSet().queryVectors.size();
7592

7693
// execute all queries in parallel and collect results

jvector-examples/src/main/java/io/github/jbellis/jvector/example/benchmarks/CountBenchmark.java

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,30 @@
2323

2424
import io.github.jbellis.jvector.example.Grid.ConfiguredSystem;
2525
import io.github.jbellis.jvector.graph.SearchResult;
26-
import org.apache.commons.math3.analysis.function.Abs;
2726

2827
/**
2928
* Measures average node‐visit and node‐expand counts over N runs.
3029
*/
3130
public class CountBenchmark extends AbstractQueryBenchmark {
32-
static private final String DEFAULT_FORMAT = ".1f";
31+
private static final String DEFAULT_FORMAT = ".1f";
3332

34-
private final boolean computeAvgNodesVisited;
35-
private final boolean computeAvgNodesExpanded;
36-
private final boolean computeAvgNodesExpandedBaseLayer;
37-
private final String formatAvgNodesVisited;
38-
private final String formatAvgNodesExpanded;
39-
private final String formatAvgNodesExpandedBaseLayer;
33+
private boolean computeAvgNodesVisited;
34+
private boolean computeAvgNodesExpanded;
35+
private boolean computeAvgNodesExpandedBaseLayer;
36+
private String formatAvgNodesVisited;
37+
private String formatAvgNodesExpanded;
38+
private String formatAvgNodesExpandedBaseLayer;
4039

41-
public CountBenchmark(boolean computeAvgNodesVisited, boolean computeAvgNodesExpanded, boolean computeAvgNodesExpandedBaseLayer,
40+
public static CountBenchmark createDefault() {
41+
return new CountBenchmark(true, false, false, DEFAULT_FORMAT, DEFAULT_FORMAT, DEFAULT_FORMAT);
42+
}
43+
44+
public static CountBenchmark createEmpty() {
45+
return new CountBenchmark(false, false, false, DEFAULT_FORMAT, DEFAULT_FORMAT, DEFAULT_FORMAT);
46+
}
47+
48+
private CountBenchmark(boolean computeAvgNodesVisited, boolean computeAvgNodesExpanded, boolean computeAvgNodesExpandedBaseLayer,
4249
String formatAvgNodesVisited, String formatAvgNodesExpanded, String formatAvgNodesExpandedBaseLayer) {
43-
if (!(computeAvgNodesVisited || computeAvgNodesExpanded || computeAvgNodesExpandedBaseLayer)) {
44-
throw new IllegalArgumentException("At least one parameter must be set to true");
45-
}
4650
this.computeAvgNodesVisited = computeAvgNodesVisited;
4751
this.computeAvgNodesExpanded = computeAvgNodesExpanded;
4852
this.computeAvgNodesExpandedBaseLayer = computeAvgNodesExpandedBaseLayer;
@@ -51,12 +55,34 @@ public CountBenchmark(boolean computeAvgNodesVisited, boolean computeAvgNodesExp
5155
this.formatAvgNodesExpandedBaseLayer = formatAvgNodesExpandedBaseLayer;
5256
}
5357

54-
public CountBenchmark() {
55-
this(true, false, false, DEFAULT_FORMAT, DEFAULT_FORMAT, DEFAULT_FORMAT);
58+
public CountBenchmark displayAvgNodesVisited() {
59+
return displayAvgNodesVisited(DEFAULT_FORMAT);
60+
}
61+
62+
public CountBenchmark displayAvgNodesVisited(String format) {
63+
this.computeAvgNodesVisited = true;
64+
this.formatAvgNodesVisited = format;
65+
return this;
5666
}
5767

58-
public CountBenchmark(String formatAvgNodesVisited, String formatAvgNodesExpanded, String formatAvgNodesExpandedBaseLayer) {
59-
this(true, true, true, formatAvgNodesVisited, formatAvgNodesExpanded, formatAvgNodesExpandedBaseLayer);
68+
public CountBenchmark displayAvgNodesExpanded() {
69+
return displayAvgNodesExpanded(DEFAULT_FORMAT);
70+
}
71+
72+
public CountBenchmark displayAvgNodesExpanded(String format) {
73+
this.computeAvgNodesExpanded = true;
74+
this.formatAvgNodesExpanded = format;
75+
return this;
76+
}
77+
78+
public CountBenchmark displayAvgNodesExpandedBaseLayer() {
79+
return displayAvgNodesExpandedBaseLayer(DEFAULT_FORMAT);
80+
}
81+
82+
public CountBenchmark displayAvgNodesExpandedBaseLayer(String format) {
83+
this.computeAvgNodesExpandedBaseLayer = true;
84+
this.formatAvgNodesExpandedBaseLayer = format;
85+
return this;
6086
}
6187

6288
@Override
@@ -72,6 +98,10 @@ public List<Metric> runBenchmark(
7298
boolean usePruning,
7399
int queryRuns) {
74100

101+
if (!(computeAvgNodesVisited || computeAvgNodesExpanded || computeAvgNodesExpandedBaseLayer)) {
102+
throw new RuntimeException("At least one metric must be displayed");
103+
}
104+
75105
LongAdder nodesVisited = new LongAdder();
76106
LongAdder nodesExpanded = new LongAdder();
77107
LongAdder nodesExpandedBaseLayer = new LongAdder();

jvector-examples/src/main/java/io/github/jbellis/jvector/example/benchmarks/ExecutionTimeBenchmark.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,22 @@
2525
* Measures average execution time over N runs through all queries in parallel.
2626
*/
2727
public class ExecutionTimeBenchmark extends AbstractQueryBenchmark {
28-
static private final String DEFAULT_FORMAT = ".1f";
28+
private static final String DEFAULT_FORMAT = ".1f";
2929

3030
private static volatile long SINK;
31-
private final String format;
31+
private String format;
3232

33-
public ExecutionTimeBenchmark(String format) {
33+
public static ExecutionTimeBenchmark createDefault() {
34+
return new ExecutionTimeBenchmark(DEFAULT_FORMAT);
35+
}
36+
37+
private ExecutionTimeBenchmark(String format) {
3438
this.format = format;
3539
}
3640

37-
public ExecutionTimeBenchmark() {
38-
this.format = DEFAULT_FORMAT;
41+
public ExecutionTimeBenchmark setFormat(String format) {
42+
this.format = format;
43+
return this;
3944
}
4045

4146
@Override

jvector-examples/src/main/java/io/github/jbellis/jvector/example/benchmarks/LatencyBenchmark.java

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,27 @@
2828
* and counts correct top‐K results.
2929
*/
3030
public class LatencyBenchmark extends AbstractQueryBenchmark {
31-
static private final String DEFAULT_FORMAT = ".3f";
31+
private static final String DEFAULT_FORMAT = ".3f";
3232

33-
private final boolean computeAvgLatency;
34-
private final boolean computeLatencySTD;
35-
private final boolean computeP999Latency;
36-
private final String formatAvgLatency;
37-
private final String formatLatencySTD;
38-
private final String formatP999Latency;
33+
private boolean computeAvgLatency;
34+
private boolean computeLatencySTD;
35+
private boolean computeP999Latency;
36+
private String formatAvgLatency;
37+
private String formatLatencySTD;
38+
private String formatP999Latency;
3939

4040
private static volatile long SINK;
4141

42-
public LatencyBenchmark(boolean computeAvgLatency, boolean computeLatencySTD, boolean computeP999Latency,
42+
public static LatencyBenchmark createDefault() {
43+
return new LatencyBenchmark(true, false, false, DEFAULT_FORMAT, DEFAULT_FORMAT, DEFAULT_FORMAT);
44+
}
45+
46+
public static LatencyBenchmark createEmpty() {
47+
return new LatencyBenchmark(false, false, false, DEFAULT_FORMAT, DEFAULT_FORMAT, DEFAULT_FORMAT);
48+
}
49+
50+
private LatencyBenchmark(boolean computeAvgLatency, boolean computeLatencySTD, boolean computeP999Latency,
4351
String formatAvgLatency, String formatLatencySTD, String formatP999Latency) {
44-
if (!(computeAvgLatency || computeLatencySTD || computeP999Latency)) {
45-
throw new IllegalArgumentException("At least one parameter must be set to true");
46-
}
4752
this.computeAvgLatency = computeAvgLatency;
4853
this.computeLatencySTD = computeLatencySTD;
4954
this.computeP999Latency = computeP999Latency;
@@ -52,12 +57,34 @@ public LatencyBenchmark(boolean computeAvgLatency, boolean computeLatencySTD, bo
5257
this.formatP999Latency = formatP999Latency;
5358
}
5459

55-
public LatencyBenchmark() {
56-
this(true, false, false, DEFAULT_FORMAT, DEFAULT_FORMAT, DEFAULT_FORMAT);
60+
public LatencyBenchmark displayAvgLatency() {
61+
return displayAvgLatency(DEFAULT_FORMAT);
5762
}
5863

59-
public LatencyBenchmark(String formatAvgLatency, String formatLatencySTD, String formatP999Latency) {
60-
this(true, true, true, formatAvgLatency, formatLatencySTD, formatP999Latency);
64+
public LatencyBenchmark displayAvgLatency(String format) {
65+
this.computeAvgLatency = true;
66+
this.formatAvgLatency = format;
67+
return this;
68+
}
69+
70+
public LatencyBenchmark displayLatencySTD() {
71+
return displayLatencySTD(DEFAULT_FORMAT);
72+
}
73+
74+
public LatencyBenchmark displayLatencySTD(String format) {
75+
this.computeLatencySTD = true;
76+
this.formatLatencySTD = format;
77+
return this;
78+
}
79+
80+
public LatencyBenchmark displayP999Latency() {
81+
return displayP999Latency(DEFAULT_FORMAT);
82+
}
83+
84+
public LatencyBenchmark displayP999Latency(String format) {
85+
this.computeP999Latency = true;
86+
this.formatP999Latency = format;
87+
return this;
6188
}
6289

6390
@Override
@@ -73,6 +100,10 @@ public List<Metric> runBenchmark(
73100
boolean usePruning,
74101
int queryRuns) {
75102

103+
if (!(computeAvgLatency || computeLatencySTD || computeP999Latency)) {
104+
throw new IllegalArgumentException("At least one parameter must be set to true");
105+
}
106+
76107
int totalQueries = cs.getDataSet().queryVectors.size();
77108
double mean = 0.0;
78109
double m2 = 0.0;

jvector-examples/src/main/java/io/github/jbellis/jvector/example/benchmarks/ThroughputBenchmark.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,27 @@
2727
* Measures throughput (queries/sec) with an optional warmup phase.
2828
*/
2929
public class ThroughputBenchmark extends AbstractQueryBenchmark {
30-
static private final String DEFAULT_FORMAT = ".1f";
30+
private static final String DEFAULT_FORMAT = ".1f";
3131

3232
private static volatile long SINK;
3333

3434
private final int warmupRuns;
3535
private final double warmupRatio;
36-
private final String format;
36+
private String format;
3737

38-
public ThroughputBenchmark(int warmupRuns, double warmupRatio, String format) {
38+
public static ThroughputBenchmark createDefault(int warmupRuns, double warmupRatio) {
39+
return new ThroughputBenchmark(warmupRuns, warmupRatio, DEFAULT_FORMAT);
40+
}
41+
42+
private ThroughputBenchmark(int warmupRuns, double warmupRatio, String format) {
3943
this.warmupRuns = warmupRuns;
4044
this.warmupRatio = warmupRatio;
4145
this.format = format;
4246
}
4347

44-
public ThroughputBenchmark(int warmupRuns, double warmupRatio) {
45-
this(warmupRuns, warmupRatio, DEFAULT_FORMAT);
48+
public ThroughputBenchmark setFormat(String format) {
49+
this.format = format;
50+
return this;
4651
}
4752

4853
@Override

0 commit comments

Comments
 (0)