Skip to content

[GR-33602] [RFC] More User-friendly Output for Native Image #3955

@fniephaus

Description

@fniephaus

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.txt
Example: 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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions