Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
6df657b
perf(java): replace deprecated ClassGraph scan with I/O-based classpa…
mashraf-222 Apr 13, 2026
4665509
perf(java): remove deprecated ClassGraph-based JavaSourceSet.build me…
mashraf-222 Apr 13, 2026
4a01c7a
perf(core): default parser input charset to UTF-8 to avoid detection …
mashraf-222 Apr 13, 2026
a611d8e
fix(kotlin): update JavaSourceSet.build call to new signature
mashraf-222 Apr 13, 2026
4412c57
perf(java): cache inferBinaryName and list results in JavacFileManager
mashraf-222 Apr 14, 2026
e768775
perf(java): pre-compile regex patterns in resolveSourcePathFromSource…
mashraf-222 Apr 14, 2026
a4da258
perf(java): use MethodHandle instead of reflection in JavaParser buil…
mashraf-222 Apr 14, 2026
bf5abef
perf(java): cache regex patterns in TypeTable.artifactsNotYetWritten
mashraf-222 Apr 14, 2026
85ec936
perf(java): cache AtomicInteger values in ImportLayoutStyle lambda
mashraf-222 Apr 14, 2026
d80b129
perf(java): pre-compile pipe regex pattern in TypeTable TSV parsing
mashraf-222 Apr 14, 2026
626a671
perf(java): pre-size HashMap and HashSet in ImportLayoutStyle conflic…
mashraf-222 Apr 14, 2026
6b324bc
perf(java): hoist Pattern.compile out of loop in TypeTable.load()
mashraf-222 Apr 14, 2026
d1df25c
perf(java): pre-size ArrayLists in Autodetect import layout statistics
mashraf-222 Apr 14, 2026
ad54253
perf(java): cache compiled regex patterns in ImportPackage constructor
mashraf-222 Apr 14, 2026
4244910
perf(java): replace stream chains with imperative loops in orderedImp…
mashraf-222 Apr 14, 2026
b9007ff
perf(java): eliminate split() allocations in IMPORT_SORTING comparator
mashraf-222 Apr 14, 2026
8cb2c1c
revert: restore charset auto-detection in Parser.Input.getSource()
mashraf-222 Apr 15, 2026
933bd82
fix: address Codex v2 review findings
mashraf-222 Apr 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2026 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite.benchmarks.java;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openrewrite.java.JavaParser;

import java.util.concurrent.TimeUnit;

/**
* Microbenchmark for JavaParser.fromJavaVersion() builder factory.
* Measures the overhead of reflection vs MethodHandle invocation.
*/
@Fork(value = 2, warmups = 1)
@Measurement(iterations = 5, time = 1)
@Warmup(iterations = 3, time = 1)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Benchmark)
public class BuilderFactoryBenchmark {

/**
* Measures the cost of repeatedly calling fromJavaVersion() to obtain
* a new builder instance. This exercises the cached supplier's invoke path.
*/
@Benchmark
public void builderFactory(Blackhole bh) {
JavaParser.Builder<? extends JavaParser, ?> builder = JavaParser.fromJavaVersion();
bh.consume(builder);
}

public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(BuilderFactoryBenchmark.class.getSimpleName())
.shouldFailOnError(true)
.build();
new Runner(opt).run();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,4 @@ public void setup() {
public void jarIOBenchmark() {
JavaSourceSet.build("main", classpath);
}

@Benchmark
public void classgraphBenchmark() {
//noinspection deprecation
JavaSourceSet.build("main", classpath, new JavaTypeCache(), false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,8 @@ public ReloadableJava11Parser build() {

private static class ByteArrayCapableJavacFileManager extends JavacFileManager {
private final List<PackageAwareJavaFileObject> classByteClasspath;
private final IdentityHashMap<JavaFileObject, String> inferBinaryNameCache = new IdentityHashMap<>();
private final HashMap<String, List<JavaFileObject>> listCache = new HashMap<>();

public ByteArrayCapableJavacFileManager(Context context,
boolean register,
Expand All @@ -396,19 +398,52 @@ public String inferBinaryName(Location location, JavaFileObject file) {
if (file instanceof PackageAwareJavaFileObject) {
return ((PackageAwareJavaFileObject) file).getClassName();
}
return super.inferBinaryName(location, file);
String cached = inferBinaryNameCache.get(file);
if (cached != null) {
return cached;
}
String result = super.inferBinaryName(location, file);
if (result != null) {
inferBinaryNameCache.put(file, result);
}
return result;
}

@Override
public void flush() {
super.flush();
inferBinaryNameCache.clear();
listCache.clear();
}

@Override
public void setLocationFromPaths(Location location, Collection<? extends Path> paths) throws IOException {
super.setLocationFromPaths(location, paths);
inferBinaryNameCache.clear();
listCache.clear();
}

@Override
public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
String key = location.getName() + ':' + packageName + ':' + kinds + ':' + recurse;
List<JavaFileObject> cached = listCache.get(key);
if (cached != null) {
return cached;
}
List<JavaFileObject> result;
if (StandardLocation.CLASS_PATH.equals(location)) {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
return Stream.concat(classByteClasspath.stream()
result = Stream.concat(classByteClasspath.stream()
.filter(jfo -> jfo.getPackage().equals(packageName)),
StreamSupport.stream(listed.spliterator(), false)
).collect(toList());
} else {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
result = listed instanceof List ? (List<JavaFileObject>) listed :
StreamSupport.stream(listed.spliterator(), false).collect(toList());
}
return super.list(location, packageName, kinds, recurse);
listCache.put(key, result);
return result;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ public ReloadableJava17Parser build() {

private static class ByteArrayCapableJavacFileManager extends JavacFileManager {
private final List<PackageAwareJavaFileObject> classByteClasspath;
private final IdentityHashMap<JavaFileObject, String> inferBinaryNameCache = new IdentityHashMap<>();
private final HashMap<ListCacheKey, List<JavaFileObject>> listCache = new HashMap<>();

private record ListCacheKey(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) {}

public ByteArrayCapableJavacFileManager(Context context,
boolean register,
Expand All @@ -367,20 +371,52 @@ public String inferBinaryName(Location location, JavaFileObject file) {
if (file instanceof PackageAwareJavaFileObject) {
return ((PackageAwareJavaFileObject) file).getClassName();
}
return super.inferBinaryName(location, file);
String cached = inferBinaryNameCache.get(file);
if (cached != null) {
return cached;
}
String result = super.inferBinaryName(location, file);
if (result != null) {
inferBinaryNameCache.put(file, result);
}
return result;
}

@Override
public void flush() {
super.flush();
inferBinaryNameCache.clear();
listCache.clear();
}

@Override
public void setLocationFromPaths(Location location, Collection<? extends Path> paths) throws IOException {
super.setLocationFromPaths(location, paths);
inferBinaryNameCache.clear();
listCache.clear();
}

@Override
public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
if (StandardLocation.CLASS_PATH.equals(location)) {
ListCacheKey key = new ListCacheKey(location, packageName, kinds, recurse);
List<JavaFileObject> cached = listCache.get(key);
if (cached != null) {
return cached;
}
List<JavaFileObject> result;
if (StandardLocation.CLASS_PATH.equals(location) && !classByteClasspath.isEmpty()) {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
return classByteClasspath.isEmpty() ? listed :
Stream.concat(classByteClasspath.stream()
result = Stream.concat(classByteClasspath.stream()
.filter(jfo -> jfo.getPackage().equals(packageName)),
StreamSupport.stream(listed.spliterator(), false)
).collect(toList());
} else {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
result = listed instanceof List ? (List<JavaFileObject>) listed :
StreamSupport.stream(listed.spliterator(), false).collect(toList());
}
return super.list(location, packageName, kinds, recurse);
listCache.put(key, result);
return result;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ public ReloadableJava21Parser build() {

private static class ByteArrayCapableJavacFileManager extends JavacFileManager {
private final List<PackageAwareJavaFileObject> classByteClasspath;
private final IdentityHashMap<JavaFileObject, String> inferBinaryNameCache = new IdentityHashMap<>();
private final HashMap<ListCacheKey, List<JavaFileObject>> listCache = new HashMap<>();

private record ListCacheKey(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) {}

public ByteArrayCapableJavacFileManager(Context context,
boolean register,
Expand All @@ -367,20 +371,52 @@ public String inferBinaryName(Location location, JavaFileObject file) {
if (file instanceof PackageAwareJavaFileObject) {
return ((PackageAwareJavaFileObject) file).getClassName();
}
return super.inferBinaryName(location, file);
String cached = inferBinaryNameCache.get(file);
if (cached != null) {
return cached;
}
String result = super.inferBinaryName(location, file);
if (result != null) {
inferBinaryNameCache.put(file, result);
}
return result;
}

@Override
public void flush() {
super.flush();
inferBinaryNameCache.clear();
listCache.clear();
}

@Override
public void setLocationFromPaths(Location location, Collection<? extends Path> paths) throws IOException {
super.setLocationFromPaths(location, paths);
inferBinaryNameCache.clear();
listCache.clear();
}

@Override
public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
if (StandardLocation.CLASS_PATH.equals(location)) {
ListCacheKey key = new ListCacheKey(location, packageName, kinds, recurse);
List<JavaFileObject> cached = listCache.get(key);
if (cached != null) {
return cached;
}
List<JavaFileObject> result;
if (StandardLocation.CLASS_PATH.equals(location) && !classByteClasspath.isEmpty()) {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
return classByteClasspath.isEmpty() ? listed :
Stream.concat(classByteClasspath.stream()
result = Stream.concat(classByteClasspath.stream()
.filter(jfo -> jfo.getPackage().equals(packageName)),
StreamSupport.stream(listed.spliterator(), false)
).collect(toList());
} else {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
result = listed instanceof List ? (List<JavaFileObject>) listed :
StreamSupport.stream(listed.spliterator(), false).collect(toList());
}
return super.list(location, packageName, kinds, recurse);
listCache.put(key, result);
return result;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ public ReloadableJava25Parser build() {

private static class ByteArrayCapableJavacFileManager extends JavacFileManager {
private final List<PackageAwareJavaFileObject> classByteClasspath;
private final IdentityHashMap<JavaFileObject, String> inferBinaryNameCache = new IdentityHashMap<>();
private final HashMap<ListCacheKey, List<JavaFileObject>> listCache = new HashMap<>();

private record ListCacheKey(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) {}

public ByteArrayCapableJavacFileManager(Context context,
boolean register,
Expand All @@ -367,20 +371,52 @@ public String inferBinaryName(Location location, JavaFileObject file) {
if (file instanceof PackageAwareJavaFileObject) {
return ((PackageAwareJavaFileObject) file).getClassName();
}
return super.inferBinaryName(location, file);
String cached = inferBinaryNameCache.get(file);
if (cached != null) {
return cached;
}
String result = super.inferBinaryName(location, file);
if (result != null) {
inferBinaryNameCache.put(file, result);
}
return result;
}

@Override
public void flush() {
super.flush();
inferBinaryNameCache.clear();
listCache.clear();
}

@Override
public void setLocationFromPaths(Location location, Collection<? extends Path> paths) throws IOException {
super.setLocationFromPaths(location, paths);
inferBinaryNameCache.clear();
listCache.clear();
}

@Override
public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
if (StandardLocation.CLASS_PATH.equals(location)) {
ListCacheKey key = new ListCacheKey(location, packageName, kinds, recurse);
List<JavaFileObject> cached = listCache.get(key);
if (cached != null) {
return cached;
}
List<JavaFileObject> result;
if (StandardLocation.CLASS_PATH.equals(location) && !classByteClasspath.isEmpty()) {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
return classByteClasspath.isEmpty() ? listed :
Stream.concat(classByteClasspath.stream()
result = Stream.concat(classByteClasspath.stream()
.filter(jfo -> jfo.getPackage().equals(packageName)),
StreamSupport.stream(listed.spliterator(), false)
).collect(toList());
} else {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
result = listed instanceof List ? (List<JavaFileObject>) listed :
StreamSupport.stream(listed.spliterator(), false).collect(toList());
}
return super.list(location, packageName, kinds, recurse);
listCache.put(key, result);
return result;
}
}

Expand Down
Loading