-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Closed
Description
Update: This feature has landed on master and will ship with the GraalVM 22.0 release.
You can try it out using a GraalVM nightly build.
Description
Currently, the output produced during native image generation is limited to a list of stages, how long each of them took to run, and GC footprint. We want to make this output more user-friendly by providing relevant information for end-users. Overall, the goal is to help users better understand what happens during image generation and how a change, whether it is on their end or ours, influences that process in terms of time to run and memory usage.
We'd like to use this issue to discuss possible features and use cases for this new output mode with the community.
TLDR: Screencast
ni-output-demo.mp4
Full Example
GraalVM Native Image 22.0.0: Generating HelloWorld...
--------------------------------------------------------------------------------
User-provided arguments:
-H:+JNI -H:+AllowFoldMethods -H:FallbackThreshold=0 \
--initialize-at-build-time=... (add -H:+ShowAllArguments to show all)
--------------------------------------------------------------------------------
[1/8] Initializing... (5.872s @ 0.96GB)
1 native library included: SDL2
12 user-provided features:
- org.mypackage.MyFeature
- org.myotherpackage.MyOtherFeature
- org.myotherpackage.MyOtherFeature
- org.myotherpackage.MyOtherFeature
- ... 8 more (add -H:+ShowAllFeatures to show all)
18 classes registered for reflection
[2/8] Performing analysis... [~**~****~**~*] (159.540s @ 2.81GB)
18,153 reachable methods
1,418 reachable classes of 3,123 loaded classes
[3/8] Building universe... (3.090s @ 2.81GB)
[4/8] Parsing methods... [**********] (29.150s @ 3.18GB)
[5/8] Inlining trivial methods... [**********] (21.721s @ 3.48GB)
[6/8] Compiling methods... [**********] (100.633s @ 4.18GB)
[7/8] Creating image with 255,854 objects... (12.594s @ 4.07GB)
31.56MB in code size
12.34MB in heap size from 512 build-time-initialized classes
[8/8] Writing 44.15MB to disk... (1,897s @ 4.07GB)
Image located at '/path/to/image'.
All generated files listed in '/path/to/build_artifacts.txt'.
--------------------------------------------------------------------------------
Top 5 packages in code area: Top 5 objects in heap:
2MB *.com.oracle 835KB *.[B
277KB *.java.util 417KB *.[C
217KB *.java.lang 121KB *.Lcom...SystemPropertiesSupplier
142KB *.java.{security,net,text,math} 120KB *.Ljava/lang/Class
77KB *.sun.nio 100KB *.[I
(add -H:+ShowAllFullBreakdowns to show all)
--------------------------------------------------------------------------------
GC Stats: 16 collection(s) in 1.687s (max committed: 4.18GB, max RSS: 4.02GB).
--------------------------------------------------------------------------------
Finished generating HelloWorld in 345.542s (1204.02s of CPU time).
(Unable to show colors and links.)
Feature List
Features are grouped by priority. Please feel free to propose changes and additional features in the comments.
Must-Have
| Name | Purpose | Complexity |
|---|---|---|
| Current stage | Users want to know which stage is currently running. Example: [3/7] Performing analysis... |
low |
| Image location | Users need to know where to find the image. Note: Native image already reports *.build_artifacts.txtExample: Image located at: '/path/to/image' |
trivial |
| Image size | Users care about the size of the image. Example: [7/7] Writing 44.15 MiB to disk... |
trivial |
| Timing info | Users want to know how much time each stage takes to run. Example: [3/7] Performing analysis... ...done in 159.540s. |
medium/low |
| Reachability info | Users want to know how many methods and classes (and packages?) are reachable. Example: 18,153 methods and 1,418 classes are reachable. |
low |
| Version info | Users need this info, for example, to file issues. Example: Generating HelloWorld with GraalVM Native Image 22.0.0... |
trivial |
| Analysis progress | Report analysis progress (e.g., based on iterations during analysis) to give users some feedback of how changes influence the time to analyze their application, without having to know about implementation details. Example see full example. |
medium |
| High-level statistics | Provide some high-level statistics of what's included in the native image (e.g., top 5 largest packages included in the binary) Example see full example. |
medium |
| Prefix | Line prefix such as [my-image:14475] helps to distinguish parallel builds (uncommon use case, but there should be an option). |
trivial |
Should Have
| Name | Purpose | Complexity |
|---|---|---|
| Show progress | Indicate progress with . (similar to JUnit) or other chars.Example: Performing Analysis... toooto with t=typeflow, o=object graph. |
low |
| List user-provided Features | Users can implement org.graalvm.nativeimage.hosted.Features and having the image builder use them during the build process. When the classpath/modulepath that the user provides, contains features that are active during build it constitutes a major potential to affect every step of the image build in various ways.Example: Found 5 user-provided Features: MyFeature, ... |
low |
| GC summary | Provide a short GC summary (e.g., number of full GCs, time in GC). An excessive number of GCs can cause slowdowns. Example: GC Stats: 16 collection(s) in 1.687s (used: 0.57; committed: 3.22; max: 11.38) |
low |
| Stage info | Provide info (or docs?) that explains what each stage is doing. Example see "Hyperlinks in console". |
medium |
| Loaded classes | Show how many classes were loaded/initialized at startup. Possibly in context with the number of reachable classes. Example: 1024 classes loaded. |
medium |
| Reflection overhead | Inform users about how many classes are registered for reflection. | low |
| Space info | Show how large the boot heap is and how much space is needed for methods and constants. Example: 12.34MiB in code size. 31.56MiB in heap size. |
unknown |
| Report RSS sizes | "Provide a more accurate picture of consumed memory. (#3879)" Question: Can this be supported across all platforms? Probably yes. Example: 1.11 GB (heap) / 1.87 GB (rss) |
medium |
Nice to Have
| Name | Purpose | Complexity |
|---|---|---|
| Colorful mode | Colorizes the output. Common in other tools (e.g., maven, gradle, ...). Turned on by default if a console is detected (System.console() != null && System.getenv("TERM") != null). Can be disabled with a flag. |
low |
| Hyperlinks in console | "Technically this is of the same kind as colors and test attributes (escape sequence based). The *.build_artifacts.txt file is a good example where this could be useful. Also for Stage info (links to our documentation for each stage) this would be neat. In the terminal output below e.g. /usr/lib/systemd/system/gdm.service is a hyperlink. More info."Example: [3/7] Performing analysis... |
low |
| GC usage | Users may want to know how much memory is consumed after each phase. Question: Is this info really needed per stage or is max heap size more interesting? Example: ...done in 159.540s (memory usage at 0.96GB). |
medium |
| List native libraries (and paths) | Allow users to understand which native libraries are included. This is something users can control and may want to optimize. Question: Is this really useful? Example: 1 native library included: SDL2 |
low |
| CPU usage | Users want to know how much CPU time is consumed during image generation. Example: Process CPU time: 120.02s |
medium |
Won't Have (this time)
| Name | Purpose | Reason |
|---|---|---|
Progress bars using \r |
Visualize progress over time. | \r incompatible with log files and some terminals. |
| Interactive dashboard | Provide overview of entire building process. | Terminal cursors incompatible with log files and some terminals. |
| Info pulled from jvmstat/JFR | Provide Java performance metrics. | Too low-level for end-users. |
| User interactions | Allow users to interact with image generation process. Example: 18,153 methods and 1,418 classes are reachable. Press C to continue or S to search for reachable elements (C/S): |
Let not use cmd line tools for something like that. |
| GraalVM banner | It is quite common for CLI tools to print a banner these days. | Wastes valuable screen estate. |
| Analysis iterations | Report number of iterations during analysis to give users a better understanding of how changes influence the analysis. Knowing how many analysis iterations happen gives valuable information on what happened/went wrong during analysis. E.g. a user might have a Feature implementation that implements duringAnalysis. If this is used in the wrong way it can mess up the analysis phase.Example: Analysis required 4 rounds of typeflow operations and 9 rounds of object graph checks. |
Analysis iterations are an implementation detail that could change at some point and should not be exposed to users. |
| Print user arguments | Show how native image was invoked. Might be redundant (e.g., Quarkus already shows CLI command) and bloat log files. Example: User-provided arguments: -H:+JNI -H:+AllowFoldMethods -H:FallbackThreshold=0 -H:+ReportExceptionStackTraces ... |
Too much output for little benefit |
| Max heap size | Track heap size over time and report max usage/size so that users know how much RAM they need to allocate for their jobs. Example: Peak memory consumption to generate the image: 5.42GiB |
Reporting peak RSS instead |
| Machine-readable output option | Provide an option to produce output readable by automation tools. Question: What would be a good output format for this? Suggestion: JSON + JSON schema |
Left for future work |
Other Things to Consider
- The output should be of reasonable size
- Native image might run as part of CI and should not bloat log files too much
- GraalVM team runs builds in parallel so logs may overlay (uncommon for end-users)
- Maven and Gradle already produce a lot of output
- Try to stick to the common terminal width of 80 characters
- Native image might run as part of CI and should not bloat log files too much
zakkak, dougxc, chumer, helpermethod, ivan-ristovic and 2 morealina-yuralina-yur and helpermethodzakkak and helpermethod