<div dir="ltr"><div>I've been analysing the performance of javac in a relatively large codebase and found classpath scanning to be the dominant factor. There are large numbers of compilation tasks, most with long classpaths  including large JARs.<br><br></div><div>I've been using the wall-time profiling mode of async-profiler to analyse where time is being spent.</div><div><br></div><div>I've been able improve build times (most dramatically on Windows, 750s reduced to 350s) by modifying javac to:</div><div><br></div><div>1. pass ziptime-info=false to the env Map of jarFsProvider.newFileSystem, which means the classpath scan in the constructor of ArchiveContainer need only read the ZIP central directory, rather then reading per-entry Extended Time metadata.</div><div>2. Extend cache lifetime for FSInfo.getJarClassPath</div><div>3. share ZipFileSystem instances across compilation tasks in a build session (multiple JavacTasks). The (custom) build tool knows which JARs are immutable.</div><div><br></div><div>I don't see any supported way to make this change via the public compiler APIs, so I'm currently using a bytecode transform to patch the implementation [1].<br><br></div><div>Change 1 is self contained and low risk -- would this be worth a patch? Other calls to newFilesystem, e.g in inferModuleName, should also be changed to for consistency.<br><br></div><div>Change 2 would not be needed if I could share a CacheFSInfo instance across a number of compilation tasks, but I don't see a way to do this via the public APIs. Am I missing something here?</div><div><br></div><div>Change 3 doesn't  seem to belong in javac, but perhaps could be accommodated with an extension point akin to StandardFileManager.setPathFactory. Two options:<br><br></div><div>// option a), a wrapper around ZipFileSystemProvider can defer javac's close() calls</div><div>void setJarFsProvider(FileSystemProvider provider)</div><div><br></div><div>// option b)<br></div><div>void setJarFileSystemFactory(JarFileSystemFactory factory)</div><div>interface JarFileSystemFactory {<br></div><div>   FileSystem newFileSystem(FileSystemProvider provider, Path path, Map<String, String> env)<br></div><div>   void close(FileSystem fileSystem)<br>}<br><br></div><div>I reviewed the Java integration in other build tools to see if this problem has been tackled elsewhere. Bazel and Gradle do use the non-public compiler API but don't appear to add this sort of caching.<br><br></div><div>Regards,<br><br></div><div>Jason Zaugg</div><div><br></div><div><br>[1] <a href="https://github.com/retronym/jarcache">https://github.com/retronym/jarcache</a></div></div>