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

[GR-52560] Size regression from GraalVM CE 23.0 to GraalVM for JDK 21 (CE) for byte[] for code metadata #8531

Open
SergejIsbrecht opened this issue Mar 5, 2024 · 2 comments
Assignees

Comments

@SergejIsbrecht
Copy link

SergejIsbrecht commented Mar 5, 2024

Describe the issue
Upgrading a large application from GraalVM 23.0 JDK17 to the latest GraalVM release for JDK21 I noticed a sharp increase in the binary size.

GraalVM 23.0 JDK17

[2/8] Performing analysis...  [******]                                                                 (143.7s @ 6.77GB)
 114,738 (95.20%) of 120,517 types reachable
 143,991 (68.49%) of 210,243 fields reachable
 481,673 (69.24%) of 695,611 methods reachable
  32,805 types, 2,979 fields, and 40,713 methods registered for reflection
      63 types,    70 fields, and    55 methods registered for JNI access
       4 native libraries: dl, pthread, rt, z
[3/8] Building universe...                                                                              (26.4s @ 8.55GB)
[4/8] Parsing methods...      [****]                                                                    (16.0s @ 6.33GB)
[5/8] Inlining methods...     [***]                                                                      (7.2s @ 4.91GB)
[6/8] Compiling methods...    [**********]                                                             (97.7s @ 11.47GB)
[7/8] Layouting methods...    [*****]                                                                  (26.5s @ 10.64GB)
[8/8] Creating image...       [*********]                                                              (82.8s @ 10.44GB)
 153.32MB (24.68%) for code area:   292,172 compilation units
 144.73MB (23.30%) for image heap:1,385,676 objects and 3 resources
 256.60MB (41.31%) for debug info generated in 28.5s
  66.50MB (10.71%) for other data
 621.16MB in total
------------------------------------------------------------------------------------------------------------------------
Top 10 origins of code area:                                Top 10 object types in image heap:
 125.58MB xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jar                35.03MB byte[] for code metadata
  11.73MB java.base                                           32.86MB java.lang.Class
   5.26MB svm.jar (Native Image)                              19.56MB byte[] for java.lang.String
   3.97MB jdk.proxy4                                          12.00MB java.lang.String
   2.59MB java.xml                                             9.63MB com.oracle.svm.core.hub.DynamicHubCompanion
 389.70kB java.management                                      9.22MB byte[] for general heap data
 301.97kB jdk.crypto.ec                                        4.02MB c.o.svm.core.hub.DynamicHub$ReflectionMetadata
 112.22kB java.logging                                         3.88MB byte[] for reflection metadata
  88.22kB java.naming                                          2.47MB java.lang.String[]
  57.55kB jdk.proxy1                                           2.26MB c.o.svm.core.hub.DynamicHub$DynamicHubMetadata
 307.48kB for 16 more packages                                13.02MB for 33289 more object types
------------------------------------------------------------------------------------------------------------------------
$ cat jdk17.dashboard.json | jq '."heap-breakdown"."heap-size" | sort_by(.size) | reverse | limit(10; .[] | select(.name))'
{
  "name": "[B",
  "size": 71131816, // <--
  "count": 390083
}
{
  "name": "Ljava/lang/Class;",
  "size": 34457184,
  "count": 114738
}
{
  "name": "Ljava/lang/String;",
  "size": 12587328,
  "count": 393354
}
....

Latest GraalVM with JDK21

[2/8] Performing analysis...  [*****]                                                                  (126.2s @ 8.45GB)
  115,030 reachable types   (95.1% of  120,937 total)
  141,186 reachable fields  (67.0% of  210,781 total)
  482,288 reachable methods (69.1% of  698,413 total)
   32,927 types, 3,020 fields, and 41,912 methods registered for reflection
       62 types,    67 fields, and    55 methods registered for JNI access
        4 native libraries: dl, pthread, rt, z
[3/8] Building universe...                                                                              (29.0s @ 9.41GB)
[4/8] Parsing methods...      [****]                                                                    (14.1s @ 5.66GB)
[5/8] Inlining methods...     [***]                                                                      (7.6s @ 7.14GB)
[6/8] Compiling methods...    [********]                                                               (75.3s @ 10.39GB)
[7/8] Layouting methods...    [*****]                                                                   (30.7s @ 8.05GB)
[8/8] Creating image...       [********]                                                                (75.6s @ 9.47GB)
 153.12MB (22.68%) for code area:   291,686 compilation units
 159.09MB (23.56%) for image heap:1,371,542 objects and 45 resources
 295.69MB (43.80%) for debug info generated in 26.0s
  67.25MB ( 9.96%) for other data
 675.15MB in total
------------------------------------------------------------------------------------------------------------------------
Top 10 origins of code area:                                Top 10 object types in image heap:
 125.09MB xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jar                51.09MB byte[] for code metadata
  12.03MB java.base                                           32.06MB java.lang.Class
   5.34MB svm.jar (Native Image)                              26.64MB byte[] for java.lang.String
   3.89MB jdk.proxy4                                          11.94MB java.lang.String
   2.58MB java.xml                                             9.65MB com.oracle.svm.core.hub.DynamicHubCompanion
 393.96kB java.management                                      4.03MB c.o.svm.core.hub.DynamicHub$ReflectionMetadata
 290.64kB jdk.crypto.ec                                        3.98MB byte[] for reflection metadata
 113.76kB java.logging                                         2.48MB java.lang.String[]
 106.85kB java.naming                                          2.12MB byte[] for general heap data
  58.46kB jdk.proxy1                                           1.81MB c.o.svm.core.hub.DynamicHub$DynamicHubMetadata
 307.01kB for 17 more packages                                13.29MB for 33371 more object types
$ cat jdk21.dashboard.json | jq '."heap-breakdown"."heap-size" | sort_by(.size) | reverse | limit(10; .[] | select(.name))'
{
  "name": "[B",
  "size": 88079096, // <--
  "count": 388267
}
{
  "name": "Ljava/lang/Class;",
  "size": 33613104,
  "count": 115027
}
{
  "name": "Ljava/lang/String;",
  "size": 12520256,
  "count": 391258
}
....

The code-size remains the same, but byte[] for code metadata increased by about ~15MB for the image heap.

Used parameters:

                        "--no-fallback",
                        "--enable-url-protocols=http",
                        // a LOT is init during build-time to reduce the binary size
                        "--initialize-at-build-time=${initAtBuildTime.joinToString(",")}",
                        "--initialize-at-run-time=${initAtRuntime.joinToString(",")}",
                        "--features=${features.joinToString(",")}",
                        "-H:-IncludeMethodData",
                        "-H:-UseServiceLoaderFeature",
                        "-H:+UnlockExperimentalVMOptions",
                        "-H:+UseSerialGC",
                        "--enable-monitoring=heapdump",
                "--verbose",
                "-H:+TraceSecurityServices",
                "-H:+TraceNativeToolUsage",
                "-H:+ReportExceptionStackTraces",
                // "-H:+BuildOutputColorful",
                "--color=always",
                "-H:+BuildOutputLinks",
                "-H:Log=registerResource:verbose"
                "-H:+DashboardCode",
                "-H:+DashboardHeap",
                "-H:-DashboardBgv",
                "-H:+DashboardJson",
                "-H:+DashboardPretty",
                "-H:DashboardDump=$buildResultDir/dashboard.json",
                "-H:BuildOutputJSONFile=$buildResultDir/build.json"

Note:
Using --strict-image-heap results in a worse binary size.

Steps to reproduce the issue
There is no reproducible because the projects contains IP. I could maybe try create another application, but I guess the impact would not be noticeably, because our application is quite large.

Any idea how to tell why the code meta data increased by 15 MB?

Describe GraalVM and your environment:

  • GraalVM version: latest GraalVM for JDK21 CE release
  • JDK major version: JDK21
  • OS: Ubuntu
  • Architecture: aarch64
@SergejIsbrecht SergejIsbrecht changed the title Size regression from GraalVM CE 23.0 to GraalVM 21 for byte[] for code metadata Size regression from GraalVM CE 23.0 to GraalVM for JDK 21 for byte[] for code metadata Mar 6, 2024
@SergejIsbrecht SergejIsbrecht changed the title Size regression from GraalVM CE 23.0 to GraalVM for JDK 21 for byte[] for code metadata Size regression from GraalVM CE 23.0 to GraalVM for JDK 21 (CE) for byte[] for code metadata Mar 6, 2024
@zakkak
Copy link
Collaborator

zakkak commented Mar 6, 2024

Hi @SergejIsbrecht, we have noticed this as well and documented our findings in https://quarkus.io/blog/mandrel-23-1-image-size-increase/

TLDR:

According to our analysis the binary size increase is attributed to two distinct changes, both of which are necessary for getting more accurate profiles when using the async-sampler.

Using --strict-image-heap results in a worse binary size.

That's interesting.

@oubidar-Abderrahim oubidar-Abderrahim self-assigned this Mar 6, 2024
@oubidar-Abderrahim oubidar-Abderrahim changed the title Size regression from GraalVM CE 23.0 to GraalVM for JDK 21 (CE) for byte[] for code metadata [GR-52560] Size regression from GraalVM CE 23.0 to GraalVM for JDK 21 (CE) for byte[] for code metadata Mar 7, 2024
@SergejIsbrecht
Copy link
Author

@christianwimmer , @thomaswue

any thoughts on this topic? I think 15 MB increase are quite substantial for features I don't even know I need, because Perf gives me everything I need with frame-pointer.

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

No branches or pull requests

5 participants