-
-
Notifications
You must be signed in to change notification settings - Fork 794
Run detekt's Gradle tasks with Gradle's Worker API #4128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -70,19 +113,18 @@ internal class DefaultCliInvoker( | |||
msg != null && "Build failed with" in msg && "issues" in msg | |||
} | |||
|
|||
private class DryRunInvoker(private val logger: Logger) : DetektInvoker { | |||
private class DryRunInvoker : DetektInvoker { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logger
can't be passed to the Worker as everything in DetektWorkParameters
must be serializable. Using println
instead means the tests still pass as anything passed to stdout is logged at QUIET level by Gradle. There's no impact on users as the dry run invoker should only be used internally.
Codecov Report
@@ Coverage Diff @@
## main #4128 +/- ##
============================================
- Coverage 84.61% 84.60% -0.01%
- Complexity 3787 3790 +3
============================================
Files 546 546
Lines 12918 12918
Branches 2268 2268
============================================
- Hits 10930 10929 -1
+ Misses 862 861 -1
- Partials 1126 1128 +2
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
Java 8 on Windows kept failing as the build runner didn't have enough memory. This is somewhat expected - Worker API starts more daemons than before, but moving the detekt classloader out of the Gradle daemon reduces the memory requirements for the Gradle daemon itself. I've therefore removed the JVM args config that increased Gradle and TestKit memory to compensate which should keep the build within the runner's memory constraints (7GB total). |
With the current implementation in a multi-module project, we will have worker processes up to
It appears to me that these additional number of gradle workers processes will impact developers using detekt. |
Is the concern about memory usage? From https://docs.gradle.org/current/userguide/worker_api.html#creating_a_worker_daemon:
So we rely on Gradle managing its resources appropriately. |
I runned this scenarios using gradle-profiler
I needed to add this task to invalidate the output of all the detekt tasks and avoid the task<Exec>("cleanDetekt") {
commandLine("bash", "-c", "rm -r **/build/reports/detekt || true")
} The raw data is here:
A summary:
No idea why plain-detekt-no-parallel maintains the same but it seems that this change makes detekt slower. This doesn't mean "no-merge". I just wanted to know the impact of this change and show it. |
Thanks for doing some benchmarking!
As expected. The question is, is the impact acceptable, given we can now use toolchains, as well as reduce memory pressure in the Gradle daemon since work is now done in separate processes? It's a tradeoff. In my opinion yes, it's still worth it, but let's wait for further feedback before merging. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm in general in favor of merging this. Thansk @BraisGabin for running some benchmarks 🙏
Given the small size of this diff, could it be possible to ship this as an opt-in (or an opt-out)? I believe our community could help us test this and identify potential early on problems.
Also @davidburstromspotify has a benchmarking suite that stress tests detekt. Would be interesting to try Worker API on that suite.
detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/Detekt.kt
Outdated
Show resolved
Hide resolved
That's reasonable. What do you think about a Gradle property called It would be an opt in first, then can upgrade to opt out later, then potentially have it as the only execution mode in future. |
Agree on this approach 👍 |
I've had...not the most fun experience with the worker API for things like this (as a consumer). Specifically Android Lint started using it, and each worker was allowed to grow to 6gb (which was the I think it's a good idea to do this in theory, but in the real world there are a lot of implications. |
Just wondering if you tried tweaking org.gradle.workers.max at all? There are also options for tweaking max memory only for the detekt tasks run using worker API which should help mitigate. A permanent option for opt in/out might be better than removing the existing setup wholesale. |
I did, but that affected parallelism overall. Lint had options to limit the worker memory, which worked, but was trial and error to get right on a per project basis. They eventually switched to run in process by default. |
This PR is stale because it has been open 90 days with no activity. Please comment or this will be closed in 7 days. |
I still plan to complete this. |
Hi, I was triggered by Gradle closing two linked issues regarding the worker api which I linked in my worker api experiment from 2020 #2896. |
It's not.
It should only do so if there's no available Gradle worker, and number of current workers < Workers API performance should fall somewhere between the current (fastest) setup, and the JavaExec (slowest) version. Workers can be reused, so yes, each worker suffers the initial performance hit as it's spun up, but that only happens for new instances and not ones that are reused. The big advantage of workers is increased parallelism in the build, as tasks using workers can run in parallel within a Gradle project (so e.g. detektMain and detektTest can run in parallel within the same project). Tasks that don't use workers can only run serially within a project. This can speed up the build if the machine has enough resources available. The other important note is that detekt's use of Worker API is opt in and behind a flag so it can be treated as an experiment for now so this will not change the existing behaviour or use of the existing classloader cache. |
I moved this PR to |
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
detekt is "allowed" to use this internally.
LGTM? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Co-authored-by: Brais Gabín <braisgabin@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. The only concern is #4128 (comment) but given that this PR is already open for over a year and it is behind a feature flag, this should be merged sooner rather than later.
Run
Detekt
task,DetektGenerateConfigTask
andDetektCreateBaselineTask
with Gradle's Worker API. This uses process isolation mode which will allow using the toolchains feature in future (#4120). Performance in general seems acceptable though I haven't done proper benchmarks.Two issues:
Neither of these issues will impact users, but contributors will face this. I see issue 2 as being more annoying. It's similar to #2957 but can happen when changes are made in any subproject, not just core modules.
Edit: I've raised issue 2 at gradle/gradle#13678 (comment). I'll open a new issue in a few days if there's no reply.