Skip to content

Commit 188a706

Browse files
committed
Group by JAR file in code area breakdown.
And extend documentation on code area.
1 parent 5ad0dc9 commit 188a706

File tree

2 files changed

+65
-46
lines changed

2 files changed

+65
-46
lines changed

docs/reference-manual/native-image/BuildOutput.md

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -20,51 +20,50 @@ Below is the example output when building a native executable of the `HelloWorld
2020
================================================================================
2121
GraalVM Native Image: Generating 'helloworld' (executable)...
2222
================================================================================
23-
[1/8] Initializing... (2.5s @ 0.21GB)
24-
Version info: 'GraalVM dev Java 11 CE'
25-
C compiler: gcc (linux, x86_64, 9.3.0)
23+
[1/8] Initializing... (3.7s @ 0.25GB)
24+
Version info: 'GraalVM dev Java 19+36-jvmci-23.0-b01 CE'
25+
Java version info: '19+36-jvmci-23.0-b01'
26+
C compiler: gcc (linux, x86_64, 11.3.0)
2627
Garbage collector: Serial GC
27-
[2/8] Performing analysis... [*******] (5.6s @ 0.46GB)
28-
2,718 (72.93%) of 3,727 types reachable
29-
3,442 (53.43%) of 6,442 fields reachable
30-
12,128 (44.82%) of 27,058 methods reachable
31-
27 types, 0 fields, and 271 methods registered for reflection
32-
58 types, 59 fields, and 52 methods registered for JNI access
28+
[2/8] Performing analysis... [****] (8.4s @ 2.56GB)
29+
2,880 (71.93%) of 4,004 types reachable
30+
3,519 (51.06%) of 6,892 fields reachable
31+
13,339 (45.71%) of 29,181 methods reachable
32+
879 types, 0 fields, and 356 methods registered for reflection
33+
57 types, 56 fields, and 52 methods registered for JNI access
3334
4 native libraries: dl, pthread, rt, z
34-
[3/8] Building universe... (0.5s @ 0.61GB)
35-
[4/8] Parsing methods... [*] (0.5s @ 0.86GB)
36-
[5/8] Inlining methods... [****] (0.5s @ 0.73GB)
37-
[6/8] Compiling methods... [**] (3.7s @ 2.38GB)
38-
[7/8] Layouting methods... [*] (0.5s @ 0.71GB)
39-
[8/8] Creating image... (2.1s @ 1.04GB)
40-
4.00MB (28.31%) for code area: 7,073 compilation units
41-
5.90MB (41.70%) for image heap: 83,319 objects and 5 resources
42-
3.24MB (22.91%) for debug info generated in 1.0s
43-
1.00MB ( 7.08%) for other data
44-
14.15MB in total
35+
[3/8] Building universe... (1.4s @ 1.85GB)
36+
[4/8] Parsing methods... [*] (1.3s @ 2.17GB)
37+
[5/8] Inlining methods... [***] (0.9s @ 0.37GB)
38+
[6/8] Compiling methods... [***] (8.4s @ 3.28GB)
39+
[7/8] Layouting methods... [**] (4.5s @ 2.41GB)
40+
[8/8] Creating image... (4.5s @ 4.90GB)
41+
4.52MB (22.97%) for code area: 7,470 compilation units
42+
7.06MB (35.89%) for image heap: 101,746 objects and 5 resources
43+
7.52MB (38.20%) for debug info generated in 1.9s
44+
593.66KB ( 2.95%) for other data
45+
19.68MB in total
4546
--------------------------------------------------------------------------------
46-
Top 10 packages in code area: Top 10 object types in image heap:
47-
632.68KB java.util 871.62KB byte[] for code metadata
48-
324.42KB java.lang 798.53KB java.lang.String
49-
223.90KB java.util.regex 774.91KB byte[] for general heap data
50-
221.62KB java.text 614.06KB java.lang.Class
51-
198.30KB com.oracle.svm.jni 492.51KB byte[] for java.lang.String
52-
166.02KB java.util.concurrent 314.81KB java.util.HashMap$Node
53-
115.44KB java.math 233.58KB c.o.s.c.h.DynamicHubCompanion
54-
98.48KB sun.text.normalizer 154.84KB java.lang.String[]
55-
97.42KB java.util.logging 139.54KB byte[] for embedded resources
56-
95.18KB c.oracle.svm.core.genscavenge 139.04KB char[]
57-
1.83MB for 118 more packages 1.29MB for 753 more object types
47+
Top 10 origins of code area: Top 10 object types in image heap:
48+
761.01KB svm.jar 1.01MB byte[] for code metadata
49+
700.69KB java.util 1000.69KB java.lang.String
50+
361.45KB java.lang 884.17KB byte[] for general heap data
51+
289.08KB java.text 686.76KB byte[] for java.lang.String
52+
239.66KB java.util.regex 659.87KB java.lang.Class
53+
206.52KB java.util.concurrent 247.50KB c.o.s.c.h.DynamicHubCompanion
54+
156.60KB java.math 239.21KB java.lang.Object[]
55+
127.50KB java.util.stream 225.42KB java.util.HashMap$Node
56+
122.44KB java.lang.invoke 173.15KB java.lang.String[]
57+
100.94KB java.util.logging 163.13KB j.u.c.ConcurrentHashMap$Node
58+
1.47MB for 76 more origins 1.70MB for 808 more object types
5859
--------------------------------------------------------------------------------
59-
0.9s (5.6% of total time) in 17 GCs | Peak RSS: 3.22GB | CPU load: 10.87
60+
0.6s (1.7% of total time) in 23 GCs | Peak RSS: 5.60GB | CPU load: 9.39
6061
--------------------------------------------------------------------------------
6162
Produced artifacts:
62-
/home/janedoe/helloworld/helloworld (executable)
63+
/home/janedoe/helloworld/helloworld (executable, debug_info)
6364
/home/janedoe/helloworld/sources (debug_info)
64-
/home/janedoe/helloworld/helloworld (debug_info)
65-
/home/janedoe/helloworld/helloworld.build_artifacts.txt
6665
================================================================================
67-
Finished generating 'helloworld' in 16.2s.
66+
Finished generating 'helloworld' in 33.6s.
6867
```
6968
7069
## Build Stages
@@ -148,6 +147,14 @@ Debug info is also generated as part of this stage (if requested).
148147
The code area contains machine code produced by the Graal compiler for all reachable methods.
149148
Therefore, reducing the number of [reachable methods](#glossary-reachability) also reduces the size of the code area.
150149
150+
##### <a name="glossary-code-area-origins"></a>Origins of Code Area
151+
To help users understand where the machine code of the code area comes from, the build output shows a breakdown of the top origins.
152+
An origin is a group of Java sources and can be a JAR file, a package name, or a class name, depending on the information available.
153+
The package `java.util`, for example, contains `HashMap` and other classes from the JDK.
154+
The `svm.jar` file contains internal sources for the Native Image runtime called SubstrateVM.
155+
To reduce the size of the code area and with that, the total size of the native executable, re-evaluate the dependencies of your application based on the code area breakdown.
156+
Some libraries and frameworks are better prepared for Native Image than others, and newer versions of a library or framework may improve (or worsen) their code footprint.
157+
151158
#### <a name="glossary-image-heap"></a>Image Heap
152159
The heap contains reachable objects such as static application data, metadata, and `byte[]` for different purposes (see below).
153160

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.lang.management.OperatingSystemMXBean;
3434
import java.lang.reflect.Field;
3535
import java.nio.file.Path;
36+
import java.security.CodeSource;
3637
import java.util.ArrayList;
3738
import java.util.Collection;
3839
import java.util.Comparator;
@@ -108,8 +109,6 @@ public class ProgressReporter {
108109
private static final boolean IS_CI = System.console() == null || System.getenv("CI") != null;
109110
private static final boolean IS_DUMB_TERM = isDumbTerm();
110111
private static final int MAX_NUM_BREAKDOWN = 10;
111-
private static final String CODE_BREAKDOWN_TITLE = String.format("Top %d packages in code area:", MAX_NUM_BREAKDOWN);
112-
private static final String HEAP_BREAKDOWN_TITLE = String.format("Top %d object types in image heap:", MAX_NUM_BREAKDOWN);
113112
private static final String STAGE_DOCS_URL = "https://github.com/oracle/graal/blob/master/docs/reference-manual/native-image/BuildOutput.md";
114113
private static final double EXCESSIVE_GC_MIN_THRESHOLD_MILLIS = 15_000;
115114
private static final double EXCESSIVE_GC_RATIO = 0.5;
@@ -487,12 +486,23 @@ public void createBreakdowns(HostedMetaAccess metaAccess, Collection<CompileTask
487486

488487
private void calculateCodeBreakdown(Collection<CompileTask> compilationTasks) {
489488
for (CompileTask task : compilationTasks) {
490-
String classOrPackageName = task.method.format("%H");
491-
int lastDotIndex = classOrPackageName.lastIndexOf('.');
492-
if (lastDotIndex > 0) {
493-
classOrPackageName = classOrPackageName.substring(0, lastDotIndex);
489+
CodeSource codeSource = task.method.getDeclaringClass().getJavaClass().getProtectionDomain().getCodeSource();
490+
String key = null;
491+
if (codeSource != null && codeSource.getLocation() != null) {
492+
String path = codeSource.getLocation().getPath();
493+
if (path.endsWith(".jar")) {
494+
// Use String API to determine basename of path to handle both / and \.
495+
key = path.substring(Math.max(path.lastIndexOf('/') + 1, path.lastIndexOf('\\') + 1));
496+
}
497+
}
498+
if (key == null) {
499+
key = task.method.format("%H");
500+
int lastDotIndex = key.lastIndexOf('.');
501+
if (lastDotIndex > 0) {
502+
key = key.substring(0, lastDotIndex);
503+
}
494504
}
495-
codeBreakdown.merge(classOrPackageName, (long) task.result.getTargetCodeSize(), Long::sum);
505+
codeBreakdown.merge(key, (long) task.result.getTargetCodeSize(), Long::sum);
496506
}
497507
}
498508

@@ -555,7 +565,9 @@ private void printBreakdowns() {
555565
.sorted(Entry.comparingByValue(Comparator.reverseOrder())).iterator();
556566

557567
final TwoColumnPrinter p = new TwoColumnPrinter();
558-
p.l().yellowBold().a(CODE_BREAKDOWN_TITLE).jumpToMiddle().a(HEAP_BREAKDOWN_TITLE).reset().flushln();
568+
p.l().yellowBold().a(String.format("Top %d ", MAX_NUM_BREAKDOWN)).doclink("origins", "#glossary-code-area-origins").a(" of code area:")
569+
.jumpToMiddle()
570+
.a(String.format("Top %d object types in image heap:", MAX_NUM_BREAKDOWN)).reset().flushln();
559571

560572
long printedCodeBytes = 0;
561573
long printedHeapBytes = 0;
@@ -593,7 +605,7 @@ private void printBreakdowns() {
593605
int numHeapItems = heapBreakdown.size();
594606
long totalCodeBytes = codeBreakdown.values().stream().collect(Collectors.summingLong(Long::longValue));
595607
long totalHeapBytes = heapBreakdown.values().stream().collect(Collectors.summingLong(Long::longValue));
596-
p.l().a(String.format("%9s for %s more packages", Utils.bytesToHuman(totalCodeBytes - printedCodeBytes), numCodeItems - printedCodeItems))
608+
p.l().a(String.format("%9s for %s more ", Utils.bytesToHuman(totalCodeBytes - printedCodeBytes), numCodeItems - printedCodeItems)).doclink("origins", "#glossary-code-area-origins")
597609
.jumpToMiddle()
598610
.a(String.format("%9s for %s more object types", Utils.bytesToHuman(totalHeapBytes - printedHeapBytes), numHeapItems - printedHeapItems)).flushln();
599611
}

0 commit comments

Comments
 (0)