Jendrik Johannes
02/16/2026, 12:29 PMFileSystemAccess for snapshotting. Last week we noticed that it takes 16m on one developers Windows machine (8m on my AWS Workspace) to do the snapshot of a particular tool. Turns out, the tool consists of 16k files.
So this is probably a general Gradle snapshotting question/issue for cases where you have an insane ammout of files:
One developer spiked to replace what Gradle is doing with a (simple) custom solution based on what they did in their previous custom build system. It's not really usable as it naively snapshots each file directly and does not make any use of the "snapshot caching" and VFS of Gradle which breaks the UP-TO-DATE case. But what they did is using Files.walk(rootPath).parallel()... to process files in parallel, which significantly improved the snapshot creation (first use case) for the 16k files. If I read the Gradle code correctly, files are always processed sequentially (see DirectorySnapshotter). I wonder if there is a particular reason for not using some parallism here.
I could not find anything on this topic in the GH issues. I wonder if this ever came up before and if there are any thoughts on this. We are in a situation where it is hard for (certain) developers to understand why the new system is better than the old one if it appears so much slower. It is of course much better in the incremental case, but the "first use" case is what makes a bad impression on some. (I personally also think it is crazy that we have a "tool" consisting of 16k files - but legacy...)Vampire
02/16/2026, 12:36 PMorg.gradle.java.compile-classpath-packaging was introduced, so that even with java-library plugin the JAR is used for consumer projects and not the single files to mitigate that problem in that specific case.
See https://docs.gradle.org/current/userguide/java_library_plugin.html#sub:java_library_known_issues_windows_performanceVampire
02/16/2026, 12:37 PMAdam
02/16/2026, 7:52 PMAdam
02/16/2026, 8:06 PMJendrik Johannes
02/17/2026, 6:52 AMslow on WindowsI was assuming that it may be a Windows specific issue but have not given it much thought. But yes, now I also remember the classpath topic. This is important information I will pass on. š
snapshot the tool as one archiveInteresting idea. Unfortunately, this won't help here I think, because the idea is to check that the tool installation has not been modified since the tool was extracted. One thought I now have is that the snapshot is not needed directly after the tool has been downloaded (in the beginning of task execution). Maybe we can do the snapshotting in parallel to running the tool the first time.
like sources, docs, or license files?Yes that is the case. A lot of stuff that is not actually "the tool". I just realized that after I was typing the above. I did not get feedback yet, but I suggested exactly that (exclude the docs) and I think it will speed up things for this particular case.
Jendrik Johannes
02/17/2026, 6:55 AMit was possible to get a bit more speed by batching the filesI am just curious if this was ever tried in Gradle or if there is a specific reason not do it there. Or if it is just the assumption that it gives no significant speed up. And if a patch that introduces such parallelism would have a chance to be accepted.
Adam
02/17/2026, 11:10 AMAdam
02/17/2026, 11:11 AMorg.gradle.api.internal.artifacts.transform.UnzipTransform. Since it's part of Gradle it's unaffected by buildscript classpath changes.
https://github.com/gradle/gradle/issues/36766Adam
02/17/2026, 11:13 AMit naively snapshots each file directly and does not make any use of the "snapshot caching" and VFS of Gradle which breaks the UP-TO-DATE casejust curious: what about combining the two approaches? Create a ValueSource that uses the faster, custom parallel file checksumming to produce a file containing the checksum. Use the produced file as a regular task input for the normal VFS and up-to-date checks?
Jendrik Johannes
02/17/2026, 1:30 PMUnzipTransform . Might come in handy in the future. If we still would use Transforms in this project, it would not be enough though as we also need to extract (for the time being) 7z files and have files that (for the time being) are loaded from a network drive which is difficult to use through dependency management as file: repositories are handled different wrt. caching.Jendrik Johannes
02/17/2026, 1:30 PMFileSystemAccess.read() directly. The advantage of that, IIUC, is that it "caches" the checksum and observes the file system. So when I call it the next time in another task that uses the same tool, it will be very fast, but would still recognize if parts of the checksum need to be recomputed.
I am not sure how I could combine it with custom snapshoting. IIUC, read() needs to do it for me so that it knows which files it needs to observe.Jendrik Johannes
02/17/2026, 1:32 PMDefinitely worth investigating. I'd make an issue, and a PR. My guess is processing that many files wasn't considered.I'll give it some thought. I think I would like some feedback from someone who knows the code has worked in this area recently first. š I never worked on that part of Gradle.
wolfs
02/24/2026, 11:49 AMPathVisitor is definitely not ready to be used with a parallel stream. It relies on the order in which files are being visited. Though for a certain layer (aka one directory), it would be fine to process the files in parallel. I think the basic idea was that this is IO bound, so it doesn't help doing that in parallel anyway, though your comment seems to indicate that this is different at least for Windows.Anze Sodja
02/26/2026, 11:02 AMJendrik Johannes
02/26/2026, 11:13 AMAnze Sodja
02/26/2026, 1:24 PMDo you think "parallel processing on each layer" is something I could do as a experiment in a reasonable amount of time?From that I think the answer is yes
Jendrik Johannes
03/27/2026, 8:39 AMDirectorySnapshotter : https://github.com/gradle/gradle/pull/37305
Maybe you can run that through your pipeline to see if this is a direction you may consider.Anze Sodja
03/27/2026, 8:58 AMJendrik Johannes
03/27/2026, 9:01 AMAnze Sodja
03/27/2026, 9:50 AMJendrik Johannes
03/27/2026, 10:01 AMDirectorySnapshoter in isolation. "snapshoting a directory" is already a isolated operation. My thought was that that should be paraliasable then without changing fundamental behavior. And that it possibly has the greater effect as in large structures it is likely to have many directories.Jendrik Johannes
03/27/2026, 10:01 AMDirectorySnapshotBuilder (ans possibly other places it refers to). Maybe that is also an option - in addition or as alternative.Jendrik Johannes
03/27/2026, 10:02 AMConfiguration? Does not look right to me.Jendrik Johannes
03/27/2026, 10:04 AMat org.gradle.api.internal.provider.AbstractMinimalProvider.get(AbstractMinimalProvider.java:100)
at org.jetbrains.kotlin.gradle.tasks.KotlinCompile$ScriptFilterSpec.isSatisfiedBy(KotlinCompile.kt:178)
at org.jetbrains.kotlin.gradle.tasks.KotlinCompile$ScriptFilterSpec.isSatisfiedBy(KotlinCompile.kt:174)
at org.gradle.api.specs.AndSpec.findUnsatisfiedSpec(AndSpec.java:66)
at org.gradle.api.specs.AndSpec.isSatisfiedBy(AndSpec.java:50)
at org.gradle.internal.fingerprint.impl.PatternSetSnapshottingFilter.lambda$getAsDirectoryWalkerPredicate$1(PatternSetSnapshottingFilter.java:65)Jendrik Johannes
03/27/2026, 10:04 AMAnze Sodja
03/27/2026, 9:09 PMJendrik Johannes
03/31/2026, 6:14 AMAnze Sodja
03/31/2026, 9:38 AMJendrik Johannes
03/31/2026, 9:39 AMJendrik Johannes
03/31/2026, 2:58 PMJendrik Johannes
03/31/2026, 2:58 PMJendrik Johannes
03/31/2026, 3:18 PMwolfs
03/31/2026, 4:09 PMAnze Sodja
04/01/2026, 8:16 AM