Skip to content

Commit ddfd866

Browse files
committed
bench: fix and expand benchmark coverage
1 parent b70d32d commit ddfd866

4 files changed

Lines changed: 102 additions & 26 deletions

File tree

TODOS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
- Compilation is very slow in the presence of lots of errors
2626
- Use package graph to limit search for find-usages/goto-def
2727
- Package separately for windows, mac, linux (see https://github.com/rust-lang/rust-analyzer/blob/master/.github/workflows/release.yaml)
28+
- Add more comprehensive benchmarks covering completion, navigation, indexing, and incremental compilation
2829

2930
# Features
3031
- Autocomplete new method name based on "no such method" errors.
@@ -56,4 +57,4 @@
5657
- Implement single abstract method
5758
- Generate cases for enum
5859
- Code lens
59-
- Inherited methods
60+
- Inherited methods

scripts/benchmark.sh

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,27 @@
11

22
#!/usr/bin/env bash
33

4+
set -euo pipefail
5+
46
# Compile the benchmark
57
mvn test-compile
68

79
# Emit the dependencies classpath
810
mvn dependency:build-classpath -DincludeScope=test -Dmdep.outputFile=scripts/classpath.txt
911

10-
# Run the benchmark
11-
java -cp $(cat scripts/classpath.txt):target/classes:target/test-classes --illegal-access=warn org.openjdk.jmh.Main BenchmarkPruner
12+
java_args=(
13+
--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
14+
--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
15+
--add-exports jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
16+
--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
17+
--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
18+
--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
19+
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
20+
--add-opens jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
21+
)
22+
23+
# Run the benchmarks
24+
java "${java_args[@]}" -cp "$(cat scripts/classpath.txt):target/classes:target/test-classes" org.openjdk.jmh.Main BenchmarkPruner BenchmarkParser
1225

1326
# Clean up
14-
rm scripts/classpath.txt
27+
rm scripts/classpath.txt
Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package org.javacs;
22

3+
import java.io.IOException;
4+
import java.nio.file.Files;
35
import java.nio.file.Path;
46
import java.nio.file.Paths;
7+
import java.time.Instant;
58
import java.util.concurrent.TimeUnit;
9+
import java.util.logging.Logger;
610
import org.openjdk.jmh.annotations.*;
11+
import org.openjdk.jmh.infra.Blackhole;
712

813
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
914
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@@ -12,18 +17,45 @@ public class BenchmarkParser {
1217

1318
@State(Scope.Benchmark)
1419
public static class CompilerState {
15-
public Path file = Paths.get("src/main/java/org/javacs/JavaLanguageServer.java").normalize();
20+
public Path file;
21+
public String contents;
22+
private long version;
23+
24+
@Setup(org.openjdk.jmh.annotations.Level.Trial)
25+
public void setup() throws IOException {
26+
FileStore.reset();
27+
quietBenchmarkLogging();
28+
29+
file = Paths.get("src/main/java/org/javacs/JavaLanguageServer.java").normalize();
30+
contents = Files.readString(file);
31+
}
32+
33+
public SourceFileObject source() {
34+
return new SourceFileObject(file, contents, Instant.ofEpochMilli(++version));
35+
}
36+
37+
private static void quietBenchmarkLogging() {
38+
Main.setRootFormat();
39+
Logger.getLogger("").setLevel(java.util.logging.Level.WARNING);
40+
Logger.getLogger("main").setLevel(java.util.logging.Level.WARNING);
41+
}
1642
}
1743

1844
@Benchmark
19-
public void parse(CompilerState state) {
20-
Parser.parseFile(state.file);
45+
public void parse(CompilerState state, Blackhole blackhole) {
46+
var parse = Parser.parseJavaFileObject(state.source());
47+
blackhole.consume(parse.root);
2148
}
2249

2350
public static void main(String[] args) {
2451
var state = new CompilerState();
52+
try {
53+
state.setup();
54+
} catch (IOException e) {
55+
throw new RuntimeException(e);
56+
}
2557
while (true) {
26-
Parser.parseFile(state.file);
58+
Parser.parseJavaFileObject(state.source());
2759
}
2860
}
2961
}

src/test/java/org/javacs/BenchmarkPruner.java

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.javacs;
22

3+
import java.io.IOException;
4+
import java.nio.file.Files;
35
import java.nio.file.Paths;
46
import java.time.Instant;
57
import java.util.Collections;
@@ -9,6 +11,7 @@
911
import java.util.logging.Logger;
1012
import org.javacs.completion.PruneMethodBodies;
1113
import org.openjdk.jmh.annotations.*;
14+
import org.openjdk.jmh.infra.Blackhole;
1215

1316
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
1417
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@@ -17,19 +20,35 @@ public class BenchmarkPruner {
1720

1821
@State(Scope.Benchmark)
1922
public static class CompilerState {
20-
public SourceFileObject file = file(false);
21-
public SourceFileObject pruned = file(true);
22-
public JavaCompilerService compiler = createCompiler();
23+
public java.nio.file.Path file;
24+
public String plainContents;
25+
public String prunedContents;
26+
public JavaCompilerService compiler;
27+
private long version;
2328

24-
private SourceFileObject file(boolean prune) {
25-
var file = Paths.get("src/main/java/org/javacs/InferConfig.java").normalize();
26-
if (prune) {
27-
var task = compiler.parse(file);
28-
var contents = new PruneMethodBodies(task.task).scan(task.root, 11222L).toString();
29-
return new SourceFileObject(file, contents, Instant.now());
30-
} else {
31-
return new SourceFileObject(file);
32-
}
29+
@Setup(org.openjdk.jmh.annotations.Level.Trial)
30+
public void setup() throws IOException {
31+
FileStore.reset();
32+
quietBenchmarkLogging();
33+
34+
file = Paths.get("src/main/java/org/javacs/InferConfig.java").normalize();
35+
plainContents = Files.readString(file);
36+
compiler = createCompiler();
37+
38+
var task = compiler.parse(source(plainContents));
39+
prunedContents = new PruneMethodBodies(task.task).scan(task.root, 11222L).toString();
40+
}
41+
42+
public SourceFileObject plainSource() {
43+
return source(plainContents);
44+
}
45+
46+
public SourceFileObject prunedSource() {
47+
return source(prunedContents);
48+
}
49+
50+
private SourceFileObject source(String contents) {
51+
return new SourceFileObject(file, contents, Instant.ofEpochMilli(++version));
3352
}
3453

3554
private static JavaCompilerService createCompiler() {
@@ -40,21 +59,32 @@ private static JavaCompilerService createCompiler() {
4059
var classPath = new InferConfig(workspaceRoot).classPath();
4160
return new JavaCompilerService(classPath, Collections.emptySet(), Collections.emptySet());
4261
}
62+
63+
private static void quietBenchmarkLogging() {
64+
Main.setRootFormat();
65+
Logger.getLogger("").setLevel(java.util.logging.Level.WARNING);
66+
Logger.getLogger("main").setLevel(java.util.logging.Level.WARNING);
67+
}
4368
}
4469

4570
@Benchmark
46-
public void parsePlain(CompilerState state) {
47-
Parser.parseJavaFileObject(state.file);
71+
public void parsePlain(CompilerState state, Blackhole blackhole) {
72+
var parse = Parser.parseJavaFileObject(state.plainSource());
73+
blackhole.consume(parse.root);
4874
}
4975

5076
@Benchmark
51-
public void compilePruned(CompilerState state) {
52-
state.compiler.compile(List.of(state.pruned)).close();
77+
public void compilePruned(CompilerState state, Blackhole blackhole) {
78+
try (var compile = state.compiler.compile(List.of(state.prunedSource()))) {
79+
blackhole.consume(compile.root());
80+
}
5381
}
5482

5583
@Benchmark
56-
public void compilePlain(CompilerState state) {
57-
state.compiler.compile(List.of(state.file)).close();
84+
public void compilePlain(CompilerState state, Blackhole blackhole) {
85+
try (var compile = state.compiler.compile(List.of(state.plainSource()))) {
86+
blackhole.consume(compile.root());
87+
}
5888
}
5989

6090
private static final Logger LOG = Logger.getLogger("main");

0 commit comments

Comments
 (0)