Skip to content

Make ValidatesRunner faster: Improvements to file staging - #40320

Merged
reuvenlax merged 3 commits into
apache:masterfrom
reuvenlax:improve_test_file_staging
Sep 29, 2026
Merged

reuvenlax merged 3 commits into
apache:masterfrom
reuvenlax:improve_test_file_staging

Conversation

@reuvenlax

@reuvenlax reuvenlax commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

An attempt to better parallelize ValidatesRunner turned up a number of problems in our file staging.

1, Cache SHA-256 file hashes and directory zips

  1. Every call to p.run() would calls PipelineResource.detectClassPathResourcesToStage which used a lot of RAM. Increasing parallelism of tests caused multiple OOMs. ClassGraph.scan(numThreads) opens every JAR and directory on the classpath. However, detect(...) only ever needed the top-level File paths of the classpath elements themselves (.getClasspathFiles()), which ClassGraph resolves directly from the ClassLoader / java.class.path without opening or scanning inside the JARs., parses their ZIP central directories, enumerates every internal resource/class entry inside every JAR, and constructs an in-memory ScanResult graph.Also the ScanResult objects (which contain mmap buffers) were lease.

Fix calls ClassGraph.getClasspathFiles() directly instead of .scan(1).getClasspathFiles(). Also caches the resolves classpath, and uses a lock to ensure that only on thread resolve the classpath at a time (the other threads should then hit the cache)

@reuvenlax reuvenlax changed the title Improvements to file stagin Make ValidatesRunner faster: Improvements to file staging Sep 28, 2026
return false;
}
FileHashCacheKey that = (FileHashCacheKey) o;
return length == that.length

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically this isn't a true "equal" but just for file of same path, length, and same modified time, it will be treated equal.

We had a couple of security reports about file staging recently not sure if this would have security implications

Again, setting a retention time for the cache may mitigate potential conflicts

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unclear how this would be exploited. any exploit means that an attacker has full write access to the staging bucket, in which case they could anyway overwrite any binary with malicious code.

.put(ENVIRONMENT_PROCESS, ImmutableSet.of(processCommandOption, processVariablesOption))
.build();

private static final ConcurrentHashMap<FileHashCacheKey, HashCode> FILE_HASH_CACHE =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, consider a bounded size cache in case of long running JVMs. One can use Guava's com.google.common.cache.Cache with maximumSize. Same applies to #40321

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return cachedZip;
}
try {
File zipFile = File.createTempFile(directory.getName(), ".zip");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Note: this fixed a pre-existing temp file leak which is good)

@reuvenlax
reuvenlax merged commit 01b18a1 into apache:master Sep 29, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants