Adam
08/26/2025, 5:00 PMAdam
08/26/2025, 5:00 PMJulien Plissonneau Duquène
08/26/2025, 5:53 PMAdam
08/26/2025, 7:46 PMMartin
08/26/2025, 9:36 PMMartin
08/26/2025, 9:39 PMSUCCESS
(despite no work actually executing)Martin
08/26/2025, 9:40 PMMartin
08/26/2025, 9:41 PMAdam
08/26/2025, 9:57 PMHow does the cache key computation work? Do I have to manually hash the input files, etc..?In my project I use clang to pre-process each of the C source files, which is ideal for checksumming (changes in unused header files won't be reflected in the pre-processed output, and other changes (like comments) will be ignored.) So, yes, if the files are marked as inputs then fingerprints twice. Although, slightly differently. Gradle fingerprints the 'plain' file content, while my custom cache can use a more specialised fingerprinting. My custom cacher doesn't have to just be used in tasks though (it could be used in the configuration phase), and the files don't have to be registered as inputs (so Gradle won't finger print them), and add a custom
outputs.upToDateWhen { cacher.isUpToDate(files) }
check.Martin
08/26/2025, 9:58 PMfiles don't have to be registered as inputs (so Gradle won't finger print them)Just bypass everything 😄
Martin
08/26/2025, 9:58 PMMartin
08/26/2025, 10:02 PMVampire
08/27/2025, 9:12 AMval foo by tasks.registering(Help::class) {
outputs.file("gradlew")
outputs.cacheIf { true }
}
then this task will stay up-to-date or can also be taken from cache, no matter what you change outside this definition in the build script (unless you there you add to the logic of that task.
If on the other hand you have
val foo by tasks.registering(Help::class) {
outputs.file("gradlew")
outputs.cacheIf { true }
doLast {
println("foo")
}
}
then the build script is defining a part of the task logic and thus becomes an input for the task.
Gradle cannot (or at least does not yet) differentiate which part of the build script changed, whether it is a part of the logic for that task or whether it is an unrelated change.
You can also see what is part of the cache key and thus what is considered an input by using -Dorg.gradle.caching.debug=true
.
If your build script does not contribute to the logic of the task but still is considered an input for up-to-dateness and cache-key, then I'd say that is a bug you should report and that needs to be fixed.Martin
08/27/2025, 9:17 AMbuild-logic:runtimeClasspath
so any change there invalidates everythingVampire
08/27/2025, 9:36 AMHelp
task, so the inputs will not change even if you change the convention plugin.
Even moving that task from the build script to the convention plugin it will stay up-to-date as the inputs are identical.
If you of course talk about a custom task or a 3rd party task and so the runtime classpath of the task changes, then of course it is an input and that is good, because a change in runtime classpath can mean a different result, so the output must not be reused.Martin
08/27/2025, 9:47 AMVampire
08/27/2025, 9:51 AMMartin
08/27/2025, 9:53 AMbuildscript
by buildscript classpath
and consider you have a single one in your root project or settingsMartin
08/27/2025, 9:53 AMbuildscript classpath
contains all your tasks implementationsMartin
08/27/2025, 9:53 AMMartin
08/27/2025, 9:54 AMVampire
08/27/2025, 10:01 AMMartin
08/27/2025, 10:02 AMHaving all plugins of the whole build in a single classpath is anyway bad-practice in my opinion as you know.Ah, I didn't know that!
Martin
08/27/2025, 10:03 AMMartin
08/27/2025, 10:04 AMVampire
08/27/2025, 10:05 AMAh, I didn't know that!Oh, sorry, thought you were part of the last discussion about this here. My opinion is, just use what you use where you use it and only do things like
apply false
if there is a technical necessity, but not just declaring all in the root project just for the sake of doing it.Martin
08/27/2025, 10:05 AMMartin
08/27/2025, 10:06 AMapply false
thing is pretty dangerousMartin
08/27/2025, 10:06 AMMartin
08/27/2025, 10:07 AMapply false
somewhere, it's in the Google recommendations, etc..Vampire
08/27/2025, 10:07 AMVampire
08/27/2025, 10:08 AMapply false
thing is pretty dangerous
As well as doing the apply false
thing is pretty dangerous
Let's not again replicate that other discussion now here, this thread is hijacked enough. 😄
Whatever you do, you do it wrong, and you will sooner or later hit problems, not matter which way you follow as there is no patent recipe that works for all cases.Martin
08/27/2025, 10:10 AMMartin
08/27/2025, 10:10 AMVampire
08/27/2025, 10:11 AMMartin
08/27/2025, 10:11 AMMartin
08/27/2025, 10:12 AMVampire
08/27/2025, 10:14 AMMartin
08/27/2025, 10:15 AMMartin
08/27/2025, 10:16 AMAdam
08/28/2025, 6:14 AM"single buildscript classpath for wiring (no dependencies)" + "isolated workers" means you have a healthy lifeExcept classloader isolation causes OOM https://github.com/gradle/gradle/issues/18313. Process isolation doesn't leak, but it's often quite resource intensive. 😬
Martin
08/28/2025, 6:27 AMMartin
08/28/2025, 6:29 AMAdam
08/28/2025, 9:41 AMyou can do classloader isolation without the leaking Worker APIOh, do you mean with a manual classloader? We had to do that recently in Dokka
Martin
08/28/2025, 9:42 AMMartin
08/28/2025, 9:42 AMMartin
08/28/2025, 9:44 AMMartin
08/28/2025, 9:44 AMAdam
08/28/2025, 9:45 AMMartin
08/28/2025, 9:45 AMwhy bother using the Worker API at all?parallelism for people without configuration cache
Martin
08/28/2025, 9:46 AMMartin
08/28/2025, 9:46 AMTask
conceptsMartin
08/28/2025, 9:46 AMMartin
08/28/2025, 9:47 AMmodifying the classloader apparently affects coroutines mechanismsI'd say there should be a way to make this work. I'd be willing to investigate this if you have a reproducer
Vampire
08/28/2025, 9:48 AMVampire
08/28/2025, 9:49 AMMartin
08/28/2025, 9:51 AMMartin
08/28/2025, 9:51 AMwhile work items from within the same task action can run in parallel using the worker api.you might as well use coroutines for that or an Executor or whatever primitive you want. This problem has been solved without Workers
Martin
08/28/2025, 9:52 AMonce the memory leak is fixed, it can be used for the classloader isolation without the need for manually fiddling around with classloadersYea, that'd be good. Although I will probably keep doing the manual thing because the Worker classloaders are not completely isolated. They will force the kotlin-stdlib version for an example
Vampire
08/28/2025, 9:53 AMAdam
08/28/2025, 9:55 AMI'd say there should be a way to make this work. I'd be willing to investigate this if you have a reproducerI'll ask. I think it was related to ThreadLocals. It was more of a theoretical concern than something we found.
Martin
08/28/2025, 9:56 AMAdam
08/28/2025, 10:00 AMYes, process isolation is also a use case although not one I am interested in(more back to my original topic) What about a single, separate process that could run workers, and the process was shared for all subprojects? Would that be interesting for you?
Martin
08/28/2025, 10:02 AMVampire
08/28/2025, 10:09 AMWhat about a single, separate process that could run workers, and the process was shared for all subprojects? Would that be interesting for you?Sounds like a shared build service which you can give work to do. 🙂
Martin
08/28/2025, 12:15 PMWhat about a single, separate process that could run workers, and the process was shared for all subprojects?Sorry was in a bit of a rush earlier. To ellaborate a bit more, I have no specific interest in process isolation unless it is otherwise technically required. The two things I want: • use dependencies that potentially conflict with other plugins • do not invalidate my task if something else in the buildscript classpath changes. I think both of those can be fixed without spawning a separate process. If a separate process helps making this a reality then I'd consider it but it's not a requirement per se.
Adam
08/29/2025, 10:14 PMMartin
08/29/2025, 10:18 PMMartin
08/29/2025, 10:19 PMMartin
08/29/2025, 10:20 PMshutdown
is not calledMartin
08/29/2025, 10:20 PMMartin
08/29/2025, 10:20 PM<http://Dispatchers.IO|Dispatchers.IO>
Adam
08/29/2025, 10:20 PMI think both of those can be fixed without spawning a separate process. If a separate process helps making this a reality then I'd consider it but it's not a requirement per se.for my use-case (caching C compilations) the decision to use a separate process was mainly influenced by wanting to use an embedded DB. Using a separate process avoids headaches with merging or concurrent access.
Martin
08/29/2025, 10:21 PMMartin
08/29/2025, 10:21 PMMartin
08/29/2025, 10:22 PMMartin
08/29/2025, 10:23 PMMartin
08/29/2025, 10:25 PMdisposeGlobalStandaloneApplicationServices
so as not to leak a worker classloader
That sounds like the bigger issue TBH? Static state is dangerous but could be OK (or else we wouldn't have <http://Dispatchers.IO|Dispatchers.IO>
) but leaking memory is not OKAdam
08/29/2025, 10:25 PMThe good news is that if you control the code you can make sure shutdown is not calledI think shutdown has to be called, otherwise the coroutines will keep running, preventing the classloader from being gc'ed
Martin
08/29/2025, 10:25 PMMartin
08/29/2025, 10:25 PMMartin
08/29/2025, 10:26 PMMartin
08/29/2025, 10:29 PMdisposeGlobalStandaloneApplicationServices
could probably be made so that it is recoverable?Martin
08/29/2025, 10:29 PMdisposed
and restart the machinery next time someone comes in?Martin
08/29/2025, 10:29 PMAdam
08/29/2025, 10:31 PMAdam
08/29/2025, 10:31 PMMartin
08/29/2025, 10:32 PMAdam
08/29/2025, 10:37 PMMartin
08/29/2025, 10:38 PMMartin
08/29/2025, 10:44 PMgrug hear screams from young grugs at horror of many line of code and pointless variable and grug prepare defend self with club
yes!!Martin
08/29/2025, 10:44 PMAdam
08/30/2025, 6:13 AMYeah, I’m not 100% against the visitor pattern, despite what the grugbrain essay says. (In general, I’m not 100% for or against anything in software development.) However, I often think it’s better to encode operations directly in a tree rather than have another side thingie that performs operations over the tree. Sometimes this mixes concerns a bit, but I don’t mind that in this case.from an interview
Martin
08/30/2025, 8:20 AM