-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-4809] Rework Guava library shading. #3658
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
The current way of shading Guava is a little problematic. Code that depends on "spark-core" does not see the transitive dependency, yet classes in "spark-core" actually depend on Guava. So it's a little tricky to run unit tests that use spark-core classes, since you need a compatible version of Guava in your dependencies when running the tests. This can become a little tricky, and is kind of a bad user experience. This change modifies the way Guava is shaded so that it's applied uniformly across the Spark build. This means Guava is shaded inside spark-core itself, so that the dependency issues above are solved. Aside from that, all Spark sub-modules have their Guava references relocated, so that they refer to the relocated classes now packaged inside spark-core. Before, this was only done by the time the assembly was built, so project that did not end up inside the assembly (such as streaming backends) could still reference the original location of Guava classes). This relocation does not apply to the sub-modules under network/, though. For those cases, we want to keep the Guava dependency alive, since we want to use the same Guava as the rest of the Yarn NM when deploying the auxiliary shuffle service. For this reason, also, the network/ dependencies are shaded into the spark-core artifact too, so that the raw Guava dependency doesn't leak.
|
I ran the maven build + unit tests, and also audited the jar files in the build using the tool I wrote: I'll run some actual jobs tomorrow. |
|
Test build #24285 has finished for PR 3658 at commit
|
|
cc @mccheah |
|
BTW, credit where credit is due, I got this idea from @arahuja |
|
Test build #24792 has finished for PR 3658 at commit
|
Conflicts: streaming/pom.xml
|
Test build #25133 has finished for PR 3658 at commit
|
Conflicts: examples/pom.xml
|
Test build #25442 has finished for PR 3658 at commit
|
|
Test build #25477 has finished for PR 3658 at commit
|
|
@pwendell would appreciate some input here. Thanks! |
|
Ping. |
core/pom.xml
Outdated
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.
Is this going to inline other modules (spark-network-common and spark-network-shuffle) in the published spark-core jar?
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.
Yes. From the first comment:
For this reason, also, the network/ dependencies are shaded into the spark-core artifact too, so that the raw Guava dependency doesn't leak.
|
Hey so a couple questions about this. This does make things simpler overall in terms of the build. Some higher level questions:
|
If we choose relocation as the official way of fixing potential library version conflicts, we'll end up with a growing spark-core. I don't think there's a limit to how many classes you can add (SPARK-1520 notwithstanding), but it doesn't look very pretty, I agree. I did this mainly to fix some issues with the current way Guava is shaded, though, not as a blueprint for how to fix dependency issues going forward. (It also can confuse certain IDEs that automatically add import statements...)
That's definitely an option. Should be pretty easy to do if that's the preferred way, but I remember that it was a conscious choice to depend on the Yarn-provided Guava.
Do they provide any public APIs? If they do, then yes. Otherwise, there would be no need to publish them. |
|
Yeah, so I think it would be better to just shade guava in YARN as well. The main dependency-related constraint was that we didn't want Spark's yarn shuffle service to have any external dependencies (i.e. it should work well out of the box with YARN). But having an inlined shaded dependency doesn't matter in this regard. So I don't see any other compelling reason to use YARN's guava. Overall is easier to understand what is going on if we don't have a special case there. And inlining things that we expose as semi-public classes (there are some developer API's in those modules, IIRC), it's a bit off from the normal maven model. So for all these reasons I think it would be good to just shade it in that jar as well. |
|
Test build #26116 has finished for PR 3658 at commit
|
|
Hey @pwendell, I'll try to get to this soon. But I wanted to get your feedback on my idea for fixing the The way I see it, the cleanest way is to do the Guava shading in the earliest artifact possible; that would be The only downside I see to that is that What do you think? |
|
@vanzin yeah this is a fair point, this would mean that network/common would expose the (un-shaded) Guava classes... a bit clunky. If those classes change in the future we could get into trouble. Still, I think this is the best possible solution, provided it's well documented. If we find that Guava changes this in the future we can consider other options. |
Conflicts: assembly/pom.xml core/pom.xml
This makes all Spark-generated artifacts use the Guava defined in
the build file at runtime too. The leaked classes ("Optional" and
friends) are now exposed in a few places where they weren't before,
but hopefully that won't cause issues.
|
LGTM pending tests. @vanzin do you have more work you'd like to do on this or are you happy with it? |
|
Test build #26199 has finished for PR 3658 at commit
|
|
No, I'm done with it. Thanks for taking a look. |
|
|
||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-shade-plugin</artifactId> |
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.
why add this?
The current way of shading Guava is a little problematic. Code that
depends on "spark-core" does not see the transitive dependency, yet
classes in "spark-core" actually depend on Guava. So it's a little
tricky to run unit tests that use spark-core classes, since you need
a compatible version of Guava in your dependencies when running the
tests. This can become a little tricky, and is kind of a bad user
experience.
This change modifies the way Guava is shaded so that it's applied
uniformly across the Spark build. This means Guava is shaded inside
spark-core itself, so that the dependency issues above are solved.
Aside from that, all Spark sub-modules have their Guava references
relocated, so that they refer to the relocated classes now packaged
inside spark-core. Before, this was only done by the time the assembly
was built, so projects that did not end up inside the assembly (such
as streaming backends) could still reference the original location
of Guava classes.
The Guava classes are added to the "first" artifact Spark generates
(network-common), so that all downstream modules have the needed
classes available. Since "network-common" is a dependency of spark-core,
all Spark apps should get the relocated classes automatically.