Skip to content

Commit ee2c4d1

Browse files
committed
Share and fix ByteUtil.
It showed KB/MB/GB but calculated KiB/MiB/GiB.
1 parent 6e5cb30 commit ee2c4d1

File tree

4 files changed

+62
-51
lines changed

4 files changed

+62
-51
lines changed

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/MemoryUtil.java

+7-10
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,21 @@
3636
import java.util.regex.Matcher;
3737
import java.util.regex.Pattern;
3838

39+
import com.oracle.svm.core.ByteUtil;
3940
import com.oracle.svm.core.OS;
4041
import com.oracle.svm.core.SubstrateOptions;
4142
import com.oracle.svm.core.util.ExitStatus;
4243
import com.oracle.svm.driver.NativeImage.NativeImageError;
4344

4445
class MemoryUtil {
45-
private static final long KiB_TO_BYTES = 1024L;
46-
private static final long MiB_TO_BYTES = 1024L * KiB_TO_BYTES;
47-
private static final long GiB_TO_BYTES = 1024L * MiB_TO_BYTES;
48-
4946
/* Builder needs at least 512MiB for building a helloworld in a reasonable amount of time. */
50-
private static final long MIN_HEAP_BYTES = 512L * MiB_TO_BYTES;
47+
private static final long MIN_HEAP_BYTES = ByteUtil.bytesFromMB(512L);
5148

5249
/* Use 85% of total system memory (e.g., 7GiB * 85% ~ 6GiB) in dedicated mode. */
5350
private static final double DEDICATED_MODE_TOTAL_MEMORY_RATIO = 0.85D;
5451

5552
/* If available memory is below 8GiB, fall back to dedicated mode. */
56-
private static final long MIN_AVAILABLE_MEMORY_THRESHOLD = 8L * GiB_TO_BYTES;
53+
private static final long MIN_AVAILABLE_MEMORY_THRESHOLD = ByteUtil.bytesFromGB(8L);
5754

5855
/*
5956
* Builder uses at most 32GB to avoid disabling compressed oops (UseCompressedOops).
@@ -132,8 +129,8 @@ private static List<String> determineReasonableMaxRAMPercentage(Function<Double,
132129

133130
if (reasonableMaxMemorySize < MIN_HEAP_BYTES) {
134131
throw new NativeImageError(
135-
"There is not enough memory available on the system (got %sMiB, need at least %sMiB). Consider freeing up memory if builds are slow, for example, by closing applications that you do not need."
136-
.formatted(reasonableMaxMemorySize / MiB_TO_BYTES, MIN_HEAP_BYTES / MiB_TO_BYTES),
132+
"There is not enough memory available on the system (got %s, need at least %s). Consider freeing up memory if builds are slow, for example, by closing applications that you do not need."
133+
.formatted(ByteUtil.bytesToHuman((long) reasonableMaxMemorySize), ByteUtil.bytesToHuman(MIN_HEAP_BYTES)),
137134
null, ExitStatus.OUT_OF_MEMORY.getValue());
138135
}
139136

@@ -183,7 +180,7 @@ private static long getAvailableMemorySizeLinux() {
183180
String memAvailableLine = Files.readAllLines(Paths.get("/proc/meminfo")).stream().filter(l -> l.startsWith("MemAvailable")).findFirst().orElse("");
184181
Matcher m = Pattern.compile("^MemAvailable:\\s+(\\d+) kB").matcher(memAvailableLine);
185182
if (m.matches()) {
186-
return Long.parseLong(m.group(1)) * KiB_TO_BYTES;
183+
return ByteUtil.bytesFromKB(Long.parseLong(m.group(1)));
187184
}
188185
} catch (Exception e) {
189186
}
@@ -271,7 +268,7 @@ private static long getAvailableMemorySizeWindows() {
271268
}
272269
Matcher m = Pattern.compile("^(\\d+)\\s+").matcher(line3);
273270
if (m.matches()) {
274-
return Long.parseLong(m.group(1)) * KiB_TO_BYTES;
271+
return ByteUtil.bytesFromKB(Long.parseLong(m.group(1)));
275272
}
276273
}
277274
p.waitFor();

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ByteFormattingUtil.java substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/core/ByteUtil.java

+34-21
Original file line numberDiff line numberDiff line change
@@ -22,38 +22,51 @@
2222
* or visit www.oracle.com if you need additional information or have any
2323
* questions.
2424
*/
25-
package com.oracle.svm.hosted;
25+
package com.oracle.svm.core;
2626

27-
public class ByteFormattingUtil {
28-
private static final double BYTES_TO_KiB = 1024d;
29-
private static final double BYTES_TO_MiB = 1024d * 1024d;
30-
private static final double BYTES_TO_GiB = 1024d * 1024d * 1024d;
27+
import org.graalvm.nativeimage.Platform;
28+
import org.graalvm.nativeimage.Platforms;
3129

32-
public static String bytesToHuman(long bytes) {
33-
return bytesToHuman("%4.2f", bytes);
34-
}
30+
public class ByteUtil {
31+
private static final long BYTES_PER_KB = 1000;
32+
private static final long BYTES_PER_MB = 1000 * 1000;
33+
private static final long BYTES_PER_GB = 1000 * 1000 * 1000;
3534

36-
public static String bytesToHuman(String format, long bytes) {
37-
if (bytes < BYTES_TO_KiB) {
35+
@Platforms(Platform.HOSTED_ONLY.class)
36+
public static String bytesToHuman(long bytes) {
37+
String format = "%4.2f";
38+
if (bytes < BYTES_PER_KB) {
3839
return String.format(format, (double) bytes) + "B";
39-
} else if (bytes < BYTES_TO_MiB) {
40-
return String.format(format, bytesToKiB(bytes)) + "kB";
41-
} else if (bytes < BYTES_TO_GiB) {
42-
return String.format(format, bytesToMiB(bytes)) + "MB";
40+
} else if (bytes < BYTES_PER_MB) {
41+
return String.format(format, bytesToKB(bytes)) + "kB";
42+
} else if (bytes < BYTES_PER_GB) {
43+
return String.format(format, bytesToMB(bytes)) + "MB";
4344
} else {
44-
return String.format(format, bytesToGiB(bytes)) + "GB";
45+
return String.format(format, bytesToGB(bytes)) + "GB";
4546
}
4647
}
4748

48-
static double bytesToKiB(long bytes) {
49-
return bytes / BYTES_TO_KiB;
49+
public static long bytesFromKB(long kb) {
50+
return kb * BYTES_PER_KB;
51+
}
52+
53+
public static long bytesFromMB(long mb) {
54+
return mb * BYTES_PER_MB;
55+
}
56+
57+
public static long bytesFromGB(long gb) {
58+
return gb * BYTES_PER_GB;
59+
}
60+
61+
private static double bytesToKB(long bytes) {
62+
return bytes / (double) BYTES_PER_KB;
5063
}
5164

52-
static double bytesToGiB(long bytes) {
53-
return bytes / BYTES_TO_GiB;
65+
private static double bytesToMB(long bytes) {
66+
return bytes / (double) BYTES_PER_MB;
5467
}
5568

56-
static double bytesToMiB(long bytes) {
57-
return bytes / BYTES_TO_MiB;
69+
public static double bytesToGB(long bytes) {
70+
return bytes / (double) BYTES_PER_GB;
5871
}
5972
}

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

+15-14
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import com.oracle.svm.common.option.CommonOptionParser;
6565
import com.oracle.svm.core.BuildArtifacts;
6666
import com.oracle.svm.core.BuildArtifacts.ArtifactType;
67+
import com.oracle.svm.core.ByteUtil;
6768
import com.oracle.svm.core.SubstrateGCOptions;
6869
import com.oracle.svm.core.SubstrateOptions;
6970
import com.oracle.svm.core.SubstrateUtil;
@@ -251,7 +252,7 @@ public void printInitializeEnd(List<Feature> features, ImageClassLoader classLoa
251252
String gcName = Heap.getHeap().getGC().getName();
252253
recordJsonMetric(GeneralInfo.GC, gcName);
253254
long maxHeapSize = SubstrateGCOptions.MaxHeapSize.getValue();
254-
String maxHeapValue = maxHeapSize == 0 ? Heap.getHeap().getGC().getDefaultMaxHeapSize() : ByteFormattingUtil.bytesToHuman(maxHeapSize);
255+
String maxHeapValue = maxHeapSize == 0 ? Heap.getHeap().getGC().getDefaultMaxHeapSize() : ByteUtil.bytesToHuman(maxHeapSize);
255256
l().a(" ").doclink("Garbage collector", "#glossary-gc").a(": ").a(gcName).a(" (").doclink("max heap size", "#glossary-gc-max-heap-size").a(": ").a(maxHeapValue).a(")").println();
256257

257258
printFeatures(features);
@@ -447,7 +448,7 @@ private void printResourceInfo() {
447448

448449
l().printLineSeparator();
449450
l().yellowBold().doclink("Build resources", "#glossary-build-resources").a(":").reset().println();
450-
l().a(" - %.2fGB of memory (%.1f%% of system memory, reason: %s)", ByteFormattingUtil.bytesToGiB(maxMemory), Utils.toPercentage(maxMemory, totalMemorySize), memoryUsageReason).println();
451+
l().a(" - %.2fGB of memory (%.1f%% of system memory, reason: %s)", ByteUtil.bytesToGB(maxMemory), Utils.toPercentage(maxMemory, totalMemorySize), memoryUsageReason).println();
451452
l().a(" - %s thread(s) (%.1f%% of %s available processor(s), %s)",
452453
maxNumberOfThreads, Utils.toPercentage(maxNumberOfThreads, availableProcessors), availableProcessors, maxNumberOfThreadsSuffix).println();
453454
}
@@ -591,15 +592,15 @@ public void printCreationEnd(int imageFileSize, int heapObjectCount, long imageH
591592
stagePrinter.end(imageTimer.getTotalTime() + writeTimer.getTotalTime() + archiveTimer.getTotalTime());
592593
creationStageEndCompleted = true;
593594
String format = "%9s (%5.2f%%) for ";
594-
l().a(format, ByteFormattingUtil.bytesToHuman(codeAreaSize), Utils.toPercentage(codeAreaSize, imageFileSize))
595+
l().a(format, ByteUtil.bytesToHuman(codeAreaSize), Utils.toPercentage(codeAreaSize, imageFileSize))
595596
.doclink("code area", "#glossary-code-area").a(":%,10d compilation units", numCompilations).println();
596597
int numResources = Resources.singleton().count();
597598
recordJsonMetric(ImageDetailKey.IMAGE_HEAP_RESOURCE_COUNT, numResources);
598-
l().a(format, ByteFormattingUtil.bytesToHuman(imageHeapSize), Utils.toPercentage(imageHeapSize, imageFileSize))
599+
l().a(format, ByteUtil.bytesToHuman(imageHeapSize), Utils.toPercentage(imageHeapSize, imageFileSize))
599600
.doclink("image heap", "#glossary-image-heap").a(":%,9d objects and %,d resources", heapObjectCount, numResources).println();
600601
if (debugInfoSize > 0) {
601602
recordJsonMetric(ImageDetailKey.DEBUG_INFO_SIZE, debugInfoSize); // Optional metric
602-
DirectPrinter l = l().a(format, ByteFormattingUtil.bytesToHuman(debugInfoSize), Utils.toPercentage(debugInfoSize, imageFileSize))
603+
DirectPrinter l = l().a(format, ByteUtil.bytesToHuman(debugInfoSize), Utils.toPercentage(debugInfoSize, imageFileSize))
603604

604605
.doclink("debug info", "#glossary-debug-info");
605606
if (debugInfoTimer != null) {
@@ -612,9 +613,9 @@ public void printCreationEnd(int imageFileSize, int heapObjectCount, long imageH
612613
recordJsonMetric(ImageDetailKey.TOTAL_SIZE, imageFileSize);
613614
recordJsonMetric(ImageDetailKey.CODE_AREA_SIZE, codeAreaSize);
614615
recordJsonMetric(ImageDetailKey.NUM_COMP_UNITS, numCompilations);
615-
l().a(format, ByteFormattingUtil.bytesToHuman(otherBytes), Utils.toPercentage(otherBytes, imageFileSize))
616+
l().a(format, ByteUtil.bytesToHuman(otherBytes), Utils.toPercentage(otherBytes, imageFileSize))
616617
.doclink("other data", "#glossary-other-data").println();
617-
l().a("%9s in total", ByteFormattingUtil.bytesToHuman(imageFileSize)).println();
618+
l().a("%9s in total", ByteUtil.bytesToHuman(imageFileSize)).println();
618619
printBreakdowns();
619620
ImageSingletons.lookup(ProgressReporterFeature.class).afterBreakdowns();
620621
printRecommendations();
@@ -652,7 +653,7 @@ private void printBreakdowns() {
652653
if (packagesBySize.hasNext()) {
653654
Entry<String, Long> e = packagesBySize.next();
654655
String className = Utils.truncateClassOrPackageName(e.getKey());
655-
codeSizePart = String.format("%9s %s", ByteFormattingUtil.bytesToHuman(e.getValue()), className);
656+
codeSizePart = String.format("%9s %s", ByteUtil.bytesToHuman(e.getValue()), className);
656657
printedCodeBytes += e.getValue();
657658
printedCodeItems++;
658659
}
@@ -666,7 +667,7 @@ private void printBreakdowns() {
666667
className = Utils.truncateClassOrPackageName(className);
667668
}
668669
long byteSize = e.byteSize;
669-
heapSizePart = String.format("%9s %s", ByteFormattingUtil.bytesToHuman(byteSize), className);
670+
heapSizePart = String.format("%9s %s", ByteUtil.bytesToHuman(byteSize), className);
670671
printedHeapBytes += byteSize;
671672
printedHeapItems++;
672673
}
@@ -680,9 +681,9 @@ private void printBreakdowns() {
680681
int numHeapItems = heapBreakdown.getSortedBreakdownEntries().size();
681682
long totalCodeBytes = codeBreakdown.values().stream().mapToLong(Long::longValue).sum();
682683

683-
p.l().a(String.format("%9s for %s more packages", ByteFormattingUtil.bytesToHuman(totalCodeBytes - printedCodeBytes), numCodeItems - printedCodeItems))
684+
p.l().a(String.format("%9s for %s more packages", ByteUtil.bytesToHuman(totalCodeBytes - printedCodeBytes), numCodeItems - printedCodeItems))
684685
.jumpToMiddle()
685-
.a(String.format("%9s for %s more object types", ByteFormattingUtil.bytesToHuman(heapBreakdown.getTotalHeapSize() - printedHeapBytes), numHeapItems - printedHeapItems))
686+
.a(String.format("%9s for %s more object types", ByteUtil.bytesToHuman(heapBreakdown.getTotalHeapSize() - printedHeapBytes), numHeapItems - printedHeapItems))
686687
.flushln();
687688
}
688689

@@ -838,7 +839,7 @@ private void printResourceStatistics() {
838839
.doclink("GCs", "#glossary-garbage-collections");
839840
long peakRSS = ProgressReporterCHelper.getPeakRSS();
840841
if (peakRSS >= 0) {
841-
p.a(" | ").doclink("Peak RSS", "#glossary-peak-rss").a(": ").a("%.2fGB", ByteFormattingUtil.bytesToGiB(peakRSS));
842+
p.a(" | ").doclink("Peak RSS", "#glossary-peak-rss").a(": ").a("%.2fGB", ByteUtil.bytesToGB(peakRSS));
842843
}
843844
recordJsonMetric(ResourceUsageKey.PEAK_RSS, (peakRSS >= 0 ? peakRSS : UNAVAILABLE_METRIC));
844845
long processCPUTime = getOperatingSystemMXBean().getProcessCpuTime();
@@ -863,7 +864,7 @@ private void checkForExcessiveGarbageCollection() {
863864
.a(": %.1fs spent in %d GCs during the last stage, taking up %.2f%% of the time.",
864865
Utils.millisToSeconds(gcTimeDeltaMillis), currentGCStats.totalCount - lastGCStats.totalCount, ratio * 100)
865866
.println();
866-
l().a(" Please ensure more than %.2fGB of memory is available for Native Image", ByteFormattingUtil.bytesToGiB(ProgressReporterCHelper.getPeakRSS())).println();
867+
l().a(" Please ensure more than %s of memory is available for Native Image", ByteUtil.bytesToHuman(ProgressReporterCHelper.getPeakRSS())).println();
867868
l().a(" to reduce GC overhead and improve image build time.").println();
868869
}
869870
lastGCStats = currentGCStats;
@@ -900,7 +901,7 @@ private static double nanosToSeconds(double nanos) {
900901
}
901902

902903
private static double getUsedMemory() {
903-
return ByteFormattingUtil.bytesToGiB(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
904+
return ByteUtil.bytesToGB(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
904905
}
905906

906907
private static String stringFilledWith(int size, String fill) {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/ImageHeapConnectedComponentsPrinter.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@
4141
import java.util.stream.Collectors;
4242

4343
import com.oracle.graal.pointsto.BigBang;
44+
import com.oracle.svm.core.ByteUtil;
4445
import com.oracle.svm.core.util.VMError;
45-
import com.oracle.svm.hosted.ByteFormattingUtil;
4646
import com.oracle.svm.hosted.image.NativeImageHeap.HeapInclusionReason;
4747
import com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo;
4848
import com.oracle.svm.hosted.image.NativeImageHeap.ObjectReachabilityGroup;
@@ -241,7 +241,7 @@ public void printConnectedComponentsObjectHistogramReport(PrintWriter out) {
241241
String title = "Native image heap connected components report";
242242
out.println(fillHeading(title));
243243
out.println(fillHeading(imageName));
244-
out.printf("Total Heap Size: %s%n", ByteFormattingUtil.bytesToHuman(totalHeapSizeInBytes));
244+
out.printf("Total Heap Size: %s%n", ByteUtil.bytesToHuman(totalHeapSizeInBytes));
245245
ObjectReachabilityGroup[] headerGroups = {
246246
ObjectReachabilityGroup.ImageCodeInfo,
247247
ObjectReachabilityGroup.DynamicHubs,
@@ -251,10 +251,10 @@ public void printConnectedComponentsObjectHistogramReport(PrintWriter out) {
251251
long totalHeaderGroupSize = 0;
252252
for (ObjectReachabilityGroup headerGroup : headerGroups) {
253253
long groupSize = groups.get(headerGroup).sizeInBytes;
254-
out.printf("\t%s size: %s%n", headerGroup.description, ByteFormattingUtil.bytesToHuman(groupSize));
254+
out.printf("\t%s size: %s%n", headerGroup.description, ByteUtil.bytesToHuman(groupSize));
255255
totalHeaderGroupSize += groupSize;
256256
}
257-
out.printf("\tIn connected components report: %s%n", ByteFormattingUtil.bytesToHuman(totalHeapSizeInBytes - totalHeaderGroupSize));
257+
out.printf("\tIn connected components report: %s%n", ByteUtil.bytesToHuman(totalHeapSizeInBytes - totalHeaderGroupSize));
258258
out.printf("Total number of objects in the heap: %d%n", this.heap.getObjects().size());
259259
out.printf("Number of connected components in the report %d", this.connectedComponents.size());
260260
for (int i = 0; i < connectedComponents.size(); i++) {
@@ -264,7 +264,7 @@ public void printConnectedComponentsObjectHistogramReport(PrintWriter out) {
264264
HeapHistogram objectHistogram = new HeapHistogram(out);
265265
connectedComponent.getObjects().forEach(o -> objectHistogram.add(o, o.getSize()));
266266
String headingInfo = String.format("ComponentId=%d | Size=%s | Percentage of total image heap size=%.4f%%", i,
267-
ByteFormattingUtil.bytesToHuman(connectedComponent.getSizeInBytes()),
267+
ByteUtil.bytesToHuman(connectedComponent.getSizeInBytes()),
268268
percentageOfTotalHeapSize);
269269

270270
out.println();
@@ -302,7 +302,7 @@ public void printConnectedComponentsObjectHistogramReport(PrintWriter out) {
302302
groupEntry.objects.forEach(o -> objectHistogram.add(o, o.getSize()));
303303
float percentageOfTotalHeapSize = 100.0f * groupEntry.sizeInBytes / this.totalHeapSizeInBytes;
304304
String headingInfo = String.format("Group=%s | Size=%s | Percentage of total image heap size=%.4f%%", groupType,
305-
ByteFormattingUtil.bytesToHuman(groups.get(groupType).sizeInBytes),
305+
ByteUtil.bytesToHuman(groups.get(groupType).sizeInBytes),
306306
percentageOfTotalHeapSize);
307307
out.println();
308308
String fullHeading = fillHeading(headingInfo);

0 commit comments

Comments
 (0)