Skip to content
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

Revert 58 to fix spotbugs/spotbugs!819 #100

Merged
merged 9 commits into from
Feb 11, 2019
Merged

Revert 58 to fix spotbugs/spotbugs!819 #100

merged 9 commits into from
Feb 11, 2019

Conversation

KengoTODA
Copy link
Member

This PR solves a reported problem at the core project.
To avoid potential issues, it also bumps up supported Gradle version from 4.0 to 5.0.

This reverts commit a0ceea6.
It seems that this change introduced a multi-threading problem
reported at spotbugs/spotbugs#819
so I revert that commit to make gradle plugin stable.
this is necessary because worker process needs them to run SpotBugs
which depends on SLF4J.
@KengoTODA KengoTODA self-assigned this Jan 28, 2019
@KengoTODA
Copy link
Member Author

@spotbugs/everyone could you review these changes? thank you!

ThrawnCA
ThrawnCA previously approved these changes Feb 10, 2019
@@ -14,6 +14,7 @@ apply from: "$rootDir/gradle/deploy.gradle"
version = '1.6.10-SNAPSHOT'
group = "com.github.spotbugs"
def spotBugsVersion = '3.1.11'
def slf4jVersion = '1.8.0-beta2'
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we need to seriously consider dropping SLF4J and just using JUL, for maximum compatibility.

Copy link
Member Author

@KengoTODA KengoTODA Feb 11, 2019

Choose a reason for hiding this comment

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

If you mean the trouble around gradle plugin, I think all the reported issues can be solved if we stop depending on Gradle internal API that excludes SLF4J from the dependency. This PR also solves a part of them by bumping up minimum supported version to 5.0. So I still think that SLF4J is better than that horrible JUL...

Choose a reason for hiding this comment

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

+1 for JUL.. it just works.

@KengoTODA
Copy link
Member Author

Updated, please review this PR again @ThrawnCA

@oehme
Copy link

oehme commented Feb 13, 2019

Why revert using the worker API? Now you depend on internal APIs again, so your plugin could break at any time. Also, using a single request worker for every task will make your plugin much, much slower. Shouldn't instead the usage of static state be removed?

@DPUkyle
Copy link
Contributor

DPUkyle commented Feb 13, 2019

I agree with @oehme; using Gradle internal APIs is a step backwards.

If the spotbugs tool can not be quickly remedied to avoid preservation of static state, I suggest that we preserve the public API of SpotBugsTask while avoiding the Worker API or internal APIs. Instead, the @TaskAction method will invoke Project#javaexec(Action); that spawned JVM will then die at the conclusion of the task execution. While this isn't ideal from a performance POV, it should prevent the static state issues identified by @Vampire.

@KengoTODA KengoTODA added this to the 1.6.10 milestone Feb 14, 2019
@KengoTODA
Copy link
Member Author

KengoTODA commented Feb 14, 2019

I also believe that it's mandatory to remove dependency on Gradle internal API. This is why I made #104 recently.

At the same time, we need to make this product working. The reverted code in this PR introduced a trouble. To make it stable asap, I merged this PR after the user test.

Let's find the way to realize stable feature in both of feature and compatibility :)
I believe it's possible even though SpotBugs itself is thread unsafe.

@KengoTODA
Copy link
Member Author

KengoTODA commented Feb 14, 2019

JavaExec mentioned by DPUkyle seems nice. It will be nice option to solve this issue.

@Vampire
Copy link

Vampire commented Feb 14, 2019

Maybe even a combination of worker api and javaExec could make sense.
Because by using the worker api, tasks are done in parallel up to max-workers amount.
The worker implementation could then spawn a separate process.
This way you have the parallelity and still the isolation.
With the current solution I think the tasks would again be done sequentially only, as would be by only doing a javaExec.

@davidburstromspotify
Copy link
Contributor

I must admit I haven't looked closely at the holistic issue, but what's problematic about dealing with the printout or dual registration at the point it happens? I don't see a dysfunction in the checkers where they themselves keep static state during analysis.

@Vampire
Copy link

Vampire commented Feb 20, 2019

The problem is the same why in 80% of the cases when you do an invokeLater in Swing to fix a bug you even make it worse.
It is symptom treatment, not bug fixing and you just shift the problem to a less obvious and harder to solve place.
I don't know of whether there are other static things that are already broken in more subtle ways, but speaking of the plugins, imagine two projects A and B that both run with the same Gradle version and thus on the same daemon and the Spotbugs task will run on the same worker (e. g. wih --max-workers 1).
Project A uses the find-sec-bugs plugin, Project B does not.
Now you analyze project B and you get no bugs found.
Next you analyze project A, not warnings, no bugs found.
Now you analyze project B again without any change and (even without warning as there is no double registration) suddenly you get issues found.

Or you analyze A and B with different version of the same plugin, and so on.

@davidburstromspotify
Copy link
Contributor

davidburstromspotify commented Feb 20, 2019

@Vampire I totally agree with that assessment. What I'm meaning is that instead of printing a warning for every time a factory is re-registered, why not be pragmatic and warn only once? That doesn't hide the symptom, and it doesn't spam the logs, and you'll get the speedup associated with the worker API.

For sure, there could be cases where your isolation is broken. Is that an issue that people are currently struggling with, or is it more of a theoretical problem at this point?

@Vampire
Copy link

Vampire commented Feb 20, 2019

What do you gain with speedup if you get wrong results? o_O

Besides that, if he follows my suggestion to combine worker-api and javaExec, you are just a bit slower as you need to start a VM each time, but it will still be done in parallel.

@davidburstromspotify
Copy link
Contributor

@Vampire If people actually do get wrong results, it's not a gain, agreed. In our projects we run the same extensions for SpotBugs for all (hundreds of) modules, so the execution time problem is much more important to solve. The speedup with the worker API and in daemon processing was substantial, reducing the execution time with more than 75%. That being said, we can perform tests with your proposed solution and see if it performs well enough. If it is at least 50% faster than the baseline I'd consider it a success from our point of view, otherwise not.

@Vampire
Copy link

Vampire commented Feb 20, 2019

It was not in-daemon with the worker API.
The isolation level was set to PROCESS, so the tasks are done in separate worker processes, not in the daemon process.
Those were reused though.
I'd guess the most speed gain was because of the parallel execution, so it might speed up enough for you with my proposal, but I might be wrong of course.

@davidburstromspotify
Copy link
Contributor

You're right, I was under the wrong impression with how the worker API was used.

I'd be happy to test the proposal, so we can know for sure.

@ctmay4
Copy link

ctmay4 commented Mar 18, 2019

I'd like to add to what @davidburstromspotify said that the slowdown is a big deal for larger projects. We had to roll back to a prior version (1.6.9) of the plugin because it made such a huge difference in our in CI builds.

@KengoTODA
Copy link
Member Author

Feel free to share your idea to solve this problem via PR! :)

@KengoTODA
Copy link
Member Author

note: It is possible to launch SpotBugs by project.javaexec, however it cannot create SpotBugsResult instance because we cannot touch IFindBugsEngine instance after execution.

      ExecResult result = project.javaexec(new Action<JavaExecSpec>() {
		@Override
		public void execute(JavaExecSpec javaSpec) {
			javaSpec.args(spec.getArguments());
			javaSpec.setMain("edu.umd.cs.findbugs.LaunchAppropriateUI");
		}
      });

To keep current feature, we need to avoid using JavaExec, then probably need to hack a classloader?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants