-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Introduce the ability to generate AppCDS #9710
Conversation
@stuartwdouglas mind taking a quick look at this and let me know if you agree with the approach, or should we try the find a why to generate all class names on our own (which is probably a ton safer since we don't need have access to external services - although with the current approach a non-trivial class list can still be obtained)? If so, I'll proceed to add tests for all three 3 jars types (for tests the JVM needs to be launched with |
@loicmathieu, @gunnarmorling mind giving this a spin? |
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 like the concept, but in practice I think there will be the potential for a lot of problems, including:
- Big potential for mismatching versions between container and local host. I am not sure what happens in this case? Do you end up with something that won't start?
- Production databases need to be available when building, as the build runs in prod profile. There is a good chance in most cases this just won't be possible.
I think that we will likely want an approach that just loads all the classes, rather than explicitly starting the application, as even though it generates a larger image it avoids the services problem.
I also think we will want to generate this as part of image creation, so you know that you will always have the correct JVM version. I think this is easy enough with a Dockerfile, not sure how hard it will be for jib.
type.equalsIgnoreCase(PackageConfig.UBER_JAR)); | ||
} | ||
|
||
public boolean isFastFar() { |
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.
minor typo
core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/AppCDSBuildStep.java
Show resolved
Hide resolved
|
||
int exitCode; | ||
try { | ||
exitCode = new ProcessBuilder(command) |
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 think this approach is going to fail in a lot of cases, as you need all the production services to be present.
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.
It could certainly fail. I'm not saying it's a good solution - because it isn't, but even like this you still get a list classes :)
You are right that you have to have exact same version of Java for the AppCDS to work. However, the default behavior of the JVM is to just ignore the AppCDS if there is an issue for any reason. For the JVM to fail when there is an issue with AppCDS, you need to have
Yeah, that's definitely the safer approach and for the dependencies it's easy. But what do we do about the JDK classes?
Here is the thing about this approach: You need to have docker installed to make this work, in order to run the JVM of the built container image to generate the AppCDS and copy it out of the container. In conclusion I agree with you that the idea is interesting, but we do need to think about how to provide the best experience. cc @maxandersen |
Jdk classes should be mostly fine, as loading all the classes will run all the static init code. |
I am certainly missing something, as I don't get you mean here :) My question was how would we add the JDK classes to |
What I am talking about is:
|
Gotcha, thanks for the explanation |
I have to prepare for a demo today and I'll most likely be off tomorrow, so I'll probably start looking at this again at the end of the week. |
Starting with Java 13 this can be done in one path using dynamic CDS archive (no need to create the classlist upfront): http://openjdk.java.net/jeps/350 I do love the fact that it didn't depends on docker on anything else, but as Stuart said it could fail in a lot of way. We will also need a way to integrate it in our generated Dockerfile. I need to check again why I use the uberjar in my blogpost, I'm sure the normal jar didn't worked for jlink but I'm not sure for AppCDS. Maybe there is an issue with the normal jar and AppCDS not detecting all classes due to missing libs in the classloader used by AppCDS to create the class list ... |
Yeah. I was thinking thas if we get this in, then as an enhancement later on we could use this if Java 13+ is being used.
This is exactly why I did it this way - so users don't need the container image to take advantage of this - although there are a lot of caveats.
I was able to make it make it work for all types of jars - although for |
This is what I fear, it means the classlist didn't contains all the needed classes. You can enable class loading logging to check this:
|
Yeah, I was doing that when I was trying to get all types of jars to work. I just didn't have time to explore why |
I just got this crazy idea (although it's not definitely not very user friendly): What if we used the report of the used classes that GraalVM I admit that from a usability standpoint it's not great, but I wanted to put it out there to see what y'all think. P.S. It would be nice if we didn't have to actually run the whole native-image build process, but instead only utilize it to do static analysis and spit out the used classes report. |
@geoand |
@loicmathieu actually if native image analysis wasn't so slow and require extra tooling, I think it would be the perfect, because it discovers all the classes loaded in the static init phase - I don't see how you can get a better set of classes actually used at runtime without starting the application itself. But I agree that the current slowness of the process is prohibitive... Which is why I wonder if there is a way for us to only run the static init phase up until the used classes report is generated |
I'll implement @stuartwdouglas's proposal hopefully next week when done with PTO and I've taken care of some other higher priority loose ends. |
I overhauled the PR. Now we don't need to start the application at all and the classes list is created by generating a This process doesn't provide any means of adding the generated AppCDS into a generated container as that requires building a container, running it (to make use of the exact Java version for WDYT @stuartwdouglas? If you agree, I'll add some tests and documentation and the PR out of draft. |
Sounds like a good approach to start with. We'd loose the ability to have different "profiles" for different kinds of workloads, but that seems acceptable. Also you'd probably miss things like Lambda proxy classes (as CDS-able as of JDK 15-ea-b27), but that seems acceptable, too. |
Yeah, it can and should definitely be improved in follow up iterations |
With this approach you will create a real big classlist as you include all the classes from all the libraries ! You also inlude all the JDK classes. Did you try it ? Do you know it's impact on disk size, RSS and startup time ? |
Yup, we definitely want the JDK classes and the dependencies. Short of running the application (which we don't want to do), there is no other way of getting the list of classes.
I did try and and it worked well for what I tested. I would invite you to test this on the application you have in mind and see for yourself :) |
The question is not if it works but the overhead of disk size and memory consumption reagrding an implementation that build the classlist based on the application run. I'll try to test it Friday, I should have some spare time ... |
Yes, but RSS is not ony heap size, I don't know how the CDS archive is read but it can uses native memory to read it so it will impact RSS size and not a lot of heap size ... |
4fadfb9
to
1ba53d1
Compare
@stuartwdouglas since we are getting close to the cut for 1.6, I would be really grateful if you could weigh in on whether the latest implementation can be added (as experimental). Thanks |
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
core/deployment/src/main/java/io/quarkus/deployment/pkg/PackageConfig.java
Outdated
Show resolved
Hide resolved
core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/AppCDSBuildStep.java
Show resolved
Hide resolved
PR updated per review comments. I also added a test. I still need to write some docs, but I'll do that early next week. |
8484395
to
c17581a
Compare
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.
Did some proofreading.
core/deployment/src/main/java/io/quarkus/deployment/pkg/PackageConfig.java
Outdated
Show resolved
Hide resolved
core/deployment/src/main/java/io/quarkus/deployment/pkg/builditem/AppCDSRequestedBuildItem.java
Outdated
Show resolved
Hide resolved
return; | ||
} | ||
|
||
log.debug("'" + CLASSES_LIST_FILE_NAME + "' successfully created."); |
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.
debugf maybe?
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.
Good idea
core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/AppCDSBuildStep.java
Outdated
Show resolved
Hide resolved
core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/AppCDSBuildStep.java
Outdated
Show resolved
Hide resolved
Co-authored-by: Guillaume Smet <[email protected]>
Could you write a paragraph for the release notes about what it brings to the plate and how to use it? Just paste it in a comment. Thanks! |
cc @gsmet |
No description provided.