-
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
Check for code usage fluctuations in native images #36108
Check for code usage fluctuations in native images #36108
Conversation
cc @jerboaa |
import org.junit.jupiter.api.Test; | ||
|
||
@QuarkusIntegrationTest | ||
public class ImageMetricsITCase { |
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.
Looks like you expect people to copy/paste this class in various modules, then edit the constants.
Perhaps it could be reworked to help reuse of code a little? I'd especially avoid having to copy paste the report name constants everywhere.
e.g. change
buildOutput.assertValueWithinRange(EXPECTED_IMAGE_SIZE, TOLERANCE_PERCENTAGE, "image_details", "total_bytes");
to
buildOutput.expectImageSize(long expectedzie, int tolerancePercentage)
?
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.
Also, I'm wondering if you really want to allow some margin of error for each of these. For example, does it make sense to have tolerante about EXPECTED_JNI_TYPES ?
With a dedicated method you'd be able to nudge the other developers in the right direction.
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.
Perhaps it could be reworked to help reuse of code a little?
Done, it's much cleaner now and uses properties files for the expected value and the tolerance instead of code. This way it's more flexible and doesn't require code changes to add a new check.
For example, does it make sense to have tolerante about EXPECTED_JNI_TYPES ?
Sure, for some cases we can be stricter. Happy to adjust the tolerance to whatever the Quarkus team would feel comfortable with (note that the stricter the checks the more the expected test failures in the CI).
2118e75
to
ba71fc9
Compare
ba71fc9
to
863e769
Compare
LGTM so far @zakkak |
863e769
to
c77ee99
Compare
I suggest we get this integrated as is and see how it goes for a couple of weeks before adding thresholds for more tests. |
c77ee99
to
07a5443
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.
OK. Just some minor comments.
integration-tests/main/src/test/resources/image-metrics-test.properties
Outdated
Show resolved
Hide resolved
integration-tests/main/src/test/resources/image-metrics-test.properties
Outdated
Show resolved
Hide resolved
integration-tests/main/src/test/resources/image-metrics-test.properties
Outdated
Show resolved
Hide resolved
07a5443
to
4f7ecbc
Compare
This comment has been minimized.
This comment has been minimized.
It works and it's already failing :| I will update the thresholds, and try to add version specific thresholds as well so that it doesn't crash if one tests with jdk-17 instead of jdk-21 for instance |
This comment has been minimized.
This comment has been minimized.
8392e76
to
d22e4f3
Compare
This comment has been minimized.
This comment has been minimized.
That's interesting... The test fails (only for the I am running the test locally and the number of methods registered for reflection are indeed close to 7470 (+-4 methods), while on the github runner they appear to be higher with no apparent reason. It's true that the compilation process is not deterministic (meaning more code might end up being reachable) but that's a big difference :/ In fact all metrics seem to be higher on GHA for this test: GH build
Local build
|
It turns out I was running without |
d22e4f3
to
fb678cb
Compare
This comment has been minimized.
This comment has been minimized.
Test failures are irrelevant (see #37347 (comment)) |
@Sanne could you please have another look? |
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.
Seems fine to me.
|
||
@ExtendWith(BuildOutputExtension.class) | ||
@QuarkusIntegrationTest | ||
public class ImageMetricsITCase { |
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.
do I get it right that idea is to just add a test of these 17 characters in every IT test case and since the general structure is IT tests will include all the various extensions it will automagically works - no extra setup?
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, if you follow the three steps mentioned in the description of this PR you should be good to go:
- copying ImageMetricsITCase.java in the corresponding folder
- running the test once
- running the following script passing the build output json file as the first parameter.
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.
@maxandersen are you OK with this?
It would be nice if there was a writeup of what the state of the PR is after all the changes that went into it, as it would help people reviewing for the first time and free them from the burden of having to build up the context by reading all the comments. Thanks! |
@geoand the description of the PR is up to date, there is no need to go through all the comments. |
👍🏼 |
* <a href="https://github.com/oracle/graal/blob/master/docs/reference-manual/native-image/BuildOutput.md">the upstream GraalVM | ||
* documentation</a>. | ||
*/ | ||
public class BuildOutputExtension implements BeforeAllCallback { |
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 nitpick - can we improve the name of this? Perhaps NativeBuildOutputExtension
?
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.
Done
This comment has been minimized.
This comment has been minimized.
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
This aims to aid in detecting code usage fluctuations as early as possible. I set the threshold to 3% which might be a bit tight. Ideally most (if not all) ITs being tested in native mode should include such checks. This way when a dependency gets updated and brings in more bloat, or a GraalVM change results in more code becoming reachable we will be able to notice. If significant fluctuations between GraalVM/Mandrel versions are detected the annotations `@DisableIfBuiltWithGraalVMOlderThan` and `@DisableIfBuiltWithGraalVMNewerThan` may be used to run tests with different properties files. The properties files can be generated by running the following script, passing the build output json file as the first parameter and the path to the target properties file as the second parameter (it will be overwritten), after a failed run. This way enabling the check for a new integration test is a matter of: 1. copying `ImageMetricsITCase.java` in the corresponding folder 2. running the test once 3. running the following script passing the build output json file as the first parameter. ```bash KEYS=( \ image_details.total_bytes \ analysis_results.types.reachable \ analysis_results.methods.reachable \ analysis_results.fields.reachable \ analysis_results.types.reflection \ analysis_results.methods.reflection \ analysis_results.fields.reflection \ analysis_results.types.jni \ analysis_results.methods.jni \ analysis_results.fields.jni \ ) echo "# Properties file used by ImageMetricsITCase" > $2 for i in $KEYS do echo "$i=$(jq .$i $1) >> $2 echo "$i.tolerance=3 >> $2 done ```
`ImageMetricsITCase` tests are skipped for versions with undefined thresholds
63d86e6
to
2e44e78
Compare
I rebased the branch to have a more recent CI run. If things look good and there are no objections I plan to merge this tonight. |
Failing Jobs - Building 2e44e78
Full information is available in the Build summary check run. Failures⚙️ Maven Tests - JDK 17 #- Failing: integration-tests/maven
📦 integration-tests/maven✖
✖
|
@zakkak We see some failures related to that on GraalVM master built with JDK 21 here:
https://github.com/graalvm/mandrel/actions/runs/7228893522/job/19699465544#step:12:518 Edit: And Mandrel 23.1:
https://github.com/graalvm/mandrel/actions/runs/7228893522/job/19699471598#step:12:514 |
Also for Mandrel 23.1 for the
https://github.com/graalvm/mandrel/actions/runs/7228893522/job/19699470818#step:12:619 |
In Mandrel 23.1 it looks like the new field being accessed through JNI is I will just increase the value (in anticipation of the January release) along with the percentage threshold (for backwards compatibility). PR: #37813 Looking into the GraalVM + |
The GraalVM + When building GraalVM Since upstream GraalVM doesn't plan on releasing GraalVM 24.0 based on JDK 21 it's not expected to get a jvmci version bump in LabsJDK 21. Unfortunately I don't see any way to work around this. Perhaps we could make these tests to be opt-out, so that we can disable them in certain environments. WDYT? |
+1 to an opt-out. In certain runs we should just be able to configure CI to not run the metrics tests. Environment variable or property comes to mind. |
Opt-out option implemented in #37820 |
This aims to aid in detecting code usage fluctuations as early as
possible. I set the threshold to 3% which might be a bit tight.
Ideally most (if not all) ITs being tested in native mode should include
such checks. This way when a dependency gets updated and brings in more
bloat, or a GraalVM change results in more code becoming reachable we
will be able to notice.
If significant fluctuations between GraalVM/Mandrel versions are
detected the annotations
@DisableIfBuiltWithGraalVMOlderThan
and@DisableIfBuiltWithGraalVMNewerThan
may be used to run tests withdifferent properties files.
The properties files can be generated by running the following script,
passing the build output json file as the first parameter and the path
to the target properties file as the second parameter (it will be
overwritten), after a failed run. This way enabling the check for a new
integration test is a matter of:
ImageMetricsITCase.java
in the corresponding folderbuild output json file as the first parameter.
Implements part of #36066
Supersedes #36091
After a first round of feedback I can add the check to more integration tests.