Skip to content

Commit 51eded6

Browse files
committed
Implement BuildOutputCodeBreakdownFile generation
1 parent 25a0779 commit 51eded6

File tree

2 files changed

+45
-14
lines changed

2 files changed

+45
-14
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,9 @@ public static boolean hasColorsEnabled(OptionValues values) {
803803
@Option(help = "Print GC warnings as part of build output", type = OptionType.User)//
804804
public static final HostedOptionKey<Boolean> BuildOutputGCWarnings = new HostedOptionKey<>(true);
805805

806+
@Option(help = "Write code breakdown information into CSV file", type = OptionType.User)//
807+
public static final HostedOptionKey<Boolean> BuildOutputCodeBreakdownFile = new HostedOptionKey<>(false);
808+
806809
@BundleMember(role = BundleMember.Role.Output)//
807810
@Option(help = "Print build output statistics as JSON to the specified file. " +
808811
"The output conforms to the JSON schema located at: " +

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

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.io.PrintWriter;
3131
import java.lang.management.GarbageCollectorMXBean;
3232
import java.lang.management.ManagementFactory;
33+
import java.nio.file.Files;
3334
import java.nio.file.Path;
3435
import java.security.CodeSource;
3536
import java.util.ArrayList;
@@ -664,35 +665,59 @@ public String renderToString(int maxLength) {
664665
int maxLengthPackage = maxLength - moduleNamePrefix.length() - locationSuffix.length();
665666
return moduleNamePrefix + Utils.truncateFQN(packageName, maxLengthPackage) + locationSuffix;
666667
}
668+
669+
public String[] elements() {
670+
String moduleName = javaModule.isNamed() ? javaModule.getName() : "";
671+
String packageName = javaPackage == null ? "" : javaPackage.getName();
672+
String locationName = location == null ? "" : location;
673+
return new String[]{mapToNativeImageRuntime(moduleName), packageName, locationName};
674+
}
667675
}
668676

669677
static String moduleNamePrefix(Module javaModule) {
670-
if (!javaModule.isNamed()) {
671-
return "";
672-
}
673-
if (javaModule.equals(DynamicHub.class.getModule())) {
674-
return "VM ";
678+
String moduleName = javaModule.isNamed() ? javaModule.getName() : "";
679+
return Utils.truncateFQN(mapToNativeImageRuntime(moduleName), 0.10) + "/";
680+
}
681+
682+
private static String mapToNativeImageRuntime(String moduleName) {
683+
String modulePrefix = "org.graalvm.nativeimage.";
684+
if (moduleName.equals(modulePrefix + "builder")) {
685+
return modulePrefix + "runtime";
675686
}
676-
return Utils.truncateFQN(javaModule.getName(), 0.10) + "/";
687+
return moduleName;
677688
}
678689

679690
private void printBreakdowns() {
680-
if (!SubstrateOptions.BuildOutputBreakdowns.getValue()) {
681-
return;
682-
}
683-
l().printLineSeparator();
684691
Map<BreakDownClassifier, Long> codeBreakdown = CodeBreakdownProvider.getAndClear().entrySet().stream()
685692
.collect(Collectors.groupingBy(
686693
entry -> BreakDownClassifier.of(entry.getKey()),
687694
Collectors.summingLong(entry -> entry.getValue())));
688695

689-
Iterator<Entry<BreakDownClassifier, Long>> packagesBySize = codeBreakdown.entrySet().stream()
690-
.sorted(Entry.comparingByValue(Comparator.reverseOrder())).iterator();
696+
List<Entry<BreakDownClassifier, Long>> sortedBreakdownData = codeBreakdown.entrySet().stream()
697+
.sorted(Entry.comparingByValue(Comparator.reverseOrder())).toList();
698+
699+
if (SubstrateOptions.BuildOutputCodeBreakdownFile.getValue()) {
700+
String valueSeparator = ",";
701+
List<String> lines = new ArrayList<>();
702+
lines.add(String.join(valueSeparator, "Size", "Module", "Package", "Location"));
703+
sortedBreakdownData.forEach(entry -> {
704+
lines.add(entry.getValue() + valueSeparator + String.join(valueSeparator, entry.getKey().elements()));
705+
});
706+
Path breakdownFile = SubstrateOptions.getImagePath().resolve(SubstrateOptions.Name.getValue() + ".code_breakdown.csv");
707+
BuildArtifacts.singleton().add(BuildArtifacts.ArtifactType.BUILD_INFO, breakdownFile);
708+
try {
709+
Files.write(breakdownFile, lines);
710+
} catch (IOException e) {
711+
throw VMError.shouldNotReachHere("Failed generating " + breakdownFile, e);
712+
}
713+
}
691714

692-
HeapBreakdownProvider heapBreakdown = HeapBreakdownProvider.singleton();
693-
Iterator<HeapBreakdownProvider.HeapBreakdownEntry> typesBySizeInHeap = heapBreakdown.getSortedBreakdownEntries().iterator();
715+
if (!SubstrateOptions.BuildOutputBreakdowns.getValue()) {
716+
return;
717+
}
694718

695719
final TwoColumnPrinter p = new TwoColumnPrinter();
720+
l().printLineSeparator();
696721
p.l().yellowBold().a(String.format("Top %d ", MAX_NUM_BREAKDOWN)).doclink("origins", "#glossary-code-area-origins").a(" of code area:")
697722
.jumpToMiddle()
698723
.a(String.format("Top %d object types in image heap:", MAX_NUM_BREAKDOWN)).reset().flushln();
@@ -701,6 +726,9 @@ private void printBreakdowns() {
701726
long printedHeapBytes = 0;
702727
long printedCodeItems = 0;
703728
long printedHeapItems = 0;
729+
Iterator<Entry<BreakDownClassifier, Long>> packagesBySize = sortedBreakdownData.iterator();
730+
HeapBreakdownProvider heapBreakdown = HeapBreakdownProvider.singleton();
731+
Iterator<HeapBreakdownProvider.HeapBreakdownEntry> typesBySizeInHeap = heapBreakdown.getSortedBreakdownEntries().iterator();
704732
for (int i = 0; i < MAX_NUM_BREAKDOWN; i++) {
705733
String codeSizePart = "";
706734
/* <- 10% for module name -><- remainder for class FQN -><- 10% for location -> */

0 commit comments

Comments
 (0)