Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions docs/reference-manual/native-image/BuildOutput.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Below is the example output when building a native executable of the `HelloWorld
GraalVM Native Image: Generating 'helloworld' (executable)...
================================================================================
[1/8] Initializing... (2.8s @ 0.15GB)
Java version: 20+34, vendor version: GraalVM CE 20-dev+34.1
Java version: 25+13, vendor version: GraalVM CE 25-dev+13.1
Graal compiler: optimization level: 2, target machine: x86-64-v3
C compiler: gcc (linux, x86_64, 12.2.0)
Garbage collector: Serial GC (max heap size: 80% of RAM)
Expand All @@ -49,7 +49,7 @@ GraalVM Native Image: Generating 'helloworld' (executable)...
7.03MB (32.02%) for image heap: 93,301 objects and 5 resources
8.96MB (40.83%) for debug info generated in 1.0s
659.13kB ( 2.93%) for other data
21.96MB in total
21.96MB in total image size, 21.04MB in total file size
--------------------------------------------------------------------------------
Top 10 origins of code area: Top 10 object types in image heap:
4.03MB java.base 1.14MB byte[] for code metadata
Expand Down Expand Up @@ -201,6 +201,10 @@ The progress indicator is printed periodically at an increasing interval.
### <a name="stage-creating"></a>Creating Image
In this stage, the native binary is created and written to disk.
Debug info is also generated as part of this stage (if requested).
This section breaks down the total image size as well as [code area](#glossary-code-area) and [image heap](#glossary-image-heap) (see below for more details).
The total image size is calculated before linking by summing the sizes of the code area, image heap, debug information (if requested and embedded in the binary), and other data.
The total file size is the actual size of the image on disk after linking.
Typically, the file size is slightly smaller than the image size due to additional link time optimizations.

#### <a name="glossary-code-area"></a>Code Area
The code area contains machine code produced by the Graal compiler for all reachable methods.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ public class ByteFormattingUtil {
private static final double BYTES_TO_GB = 1000d * 1000d * 1000d;

public static String bytesToHuman(long bytes) {
assert bytes >= 0;
if (bytes < BYTES_TO_KB) {
return toHuman(bytes, "B");
return plainBytes(bytes, "B");
} else if (bytes < BYTES_TO_MB) {
return toHuman(bytes / BYTES_TO_KB, "kB");
} else if (bytes < BYTES_TO_GB) {
Expand All @@ -48,4 +49,9 @@ public static String bytesToHumanGB(long bytes) {
private static String toHuman(double value, String unit) {
return "%.2f%s".formatted(value, unit);
}

private static String plainBytes(long value, String unit) {
assert 0 <= value && value < BYTES_TO_KB;
return "%d%s".formatted(value, unit);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,7 @@ protected void doRun(Map<Method, CEntryPointData> entryPoints, JavaMainSupport j
compileQueue.purge();

int numCompilations = codeCache.getOrderedCompilations().size();
int imageDiskFileSize = -1;

try (StopTimer t = TimerCollection.createTimerAndStart(TimerCollection.Registry.WRITE)) {
loader.watchdog.recordActivity();
Expand All @@ -755,14 +756,21 @@ protected void doRun(Map<Method, CEntryPointData> entryPoints, JavaMainSupport j

AfterImageWriteAccessImpl afterConfig = new AfterImageWriteAccessImpl(featureHandler, loader, hUniverse, inv, tmpDir, image.getImageKind(), debug);
featureHandler.forEachFeature(feature -> feature.afterImageWrite(afterConfig));
try {
// size changes during linking and afterConfig phase
imageDiskFileSize = (int) inv.getOutputFile().toFile().length();
} catch (Exception e) {
imageDiskFileSize = -1; // we can't read a disk file size
}
}
try (StopTimer t = TimerCollection.createTimerAndStart(TimerCollection.Registry.ARCHIVE_LAYER)) {
if (ImageLayerBuildingSupport.buildingSharedLayer()) {
ImageSingletonsSupportImpl.HostedManagement.persist();
HostedImageLayerBuildingSupport.singleton().archiveLayer(imageName);
}
}
reporter.printCreationEnd(image.getImageFileSize(), heap.getLayerObjectCount(), image.getImageHeapSize(), codeCache.getCodeAreaSize(), numCompilations, image.getDebugInfoSize());
reporter.printCreationEnd(image.getImageFileSize(), heap.getLayerObjectCount(), image.getImageHeapSize(), codeCache.getCodeAreaSize(), numCompilations, image.getDebugInfoSize(),
imageDiskFileSize);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ public void setDebugInfoTimer(Timer timer) {
this.debugInfoTimer = timer;
}

public void printCreationEnd(int imageFileSize, int heapObjectCount, long imageHeapSize, int codeAreaSize, int numCompilations, int debugInfoSize) {
public void printCreationEnd(int imageFileSize, int heapObjectCount, long imageHeapSize, int codeAreaSize, int numCompilations, int debugInfoSize, int imageDiskFileSize) {
recordJsonMetric(ImageDetailKey.IMAGE_HEAP_OBJECT_COUNT, heapObjectCount);
Timer imageTimer = getTimer(TimerCollection.Registry.IMAGE);
Timer writeTimer = getTimer(TimerCollection.Registry.WRITE);
Expand Down Expand Up @@ -620,7 +620,11 @@ public void printCreationEnd(int imageFileSize, int heapObjectCount, long imageH
recordJsonMetric(ImageDetailKey.NUM_COMP_UNITS, numCompilations);
l().a(format, ByteFormattingUtil.bytesToHuman(otherBytes), Utils.toPercentage(otherBytes, imageFileSize))
.doclink("other data", "#glossary-other-data").println();
l().a("%9s in total", ByteFormattingUtil.bytesToHuman(imageFileSize)).println();
l().a("%9s in total image size", ByteFormattingUtil.bytesToHuman(imageFileSize));
if (imageDiskFileSize >= 0) {
l().a(", %s in total file size", ByteFormattingUtil.bytesToHuman(imageDiskFileSize));
}
l().println();
printBreakdowns();
ImageSingletons.lookup(ProgressReporterFeature.class).afterBreakdowns();
printRecommendations();
Expand Down
Loading