xref: /aosp_15_r20/external/cldr/tools/cldr-code/src/main/java/org/unicode/cldr/util/MemoryHelper.java (revision 912701f9769bb47905792267661f0baf2b85bed5)
1 package org.unicode.cldr.util;
2 
3 import java.text.CharacterIterator;
4 import java.text.StringCharacterIterator;
5 
6 public class MemoryHelper {
7 
8     /**
9      * Get the amount of memory still available for us to allocate, including not only freeMemory
10      * but also maxMemory - totalMemory
11      *
12      * <p>https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Runtime.html#freeMemory()
13      *
14      * <p>Generally: freeMemory <= totalMemory <= maxMemory
15      *
16      * @param callerId a string identifying the caller, used in log if verbose
17      * @param verbose if true, log the stats
18      * @return the available memory, in bytes
19      */
availableMemory(String callerId, boolean verbose)20     public static synchronized long availableMemory(String callerId, boolean verbose) {
21         final Runtime r = Runtime.getRuntime();
22         long freeMem = r.freeMemory();
23         long maxMem = r.maxMemory();
24         long totalMem = r.totalMemory();
25         if (freeMem > totalMem || totalMem > maxMem) {
26             log(callerId, "Values returned by Runtime violate assumptions!");
27             verbose = true;
28         }
29         long availMem = freeMem + maxMem - totalMem;
30         if (verbose) {
31             log(
32                     callerId,
33                     "Available memory: "
34                             + humanReadableByteCountSI(availMem)
35                             + "; free: "
36                             + humanReadableByteCountSI(freeMem)
37                             + "; max: "
38                             + humanReadableByteCountSI(maxMem)
39                             + "; total: "
40                             + humanReadableByteCountSI(totalMem));
41         }
42         return availMem;
43     }
44 
log(String callerId, String message)45     private static void log(String callerId, String message) {
46         System.out.println("MemoryHelper[" + callerId + "]: " + message);
47     }
48 
49     /**
50      * Convert a byte count to a human readable string Use SI (1 k = 1,000), not Binary (1 K =
51      * 1,024)
52      *
53      * @param bytes the number such as 1234567890
54      * @return the formatted string such as "1.2 GB"
55      *     <p>Source:
56      *     https://programming.guide/java/formatting-byte-size-to-human-readable-format.html
57      */
humanReadableByteCountSI(long bytes)58     public static String humanReadableByteCountSI(long bytes) {
59         if (-1000 < bytes && bytes < 1000) {
60             return bytes + " B";
61         }
62         CharacterIterator ci = new StringCharacterIterator("kMGTPE");
63         while (bytes <= -999_950 || bytes >= 999_950) {
64             bytes /= 1000;
65             ci.next();
66         }
67         return String.format("%.1f %cB", bytes / 1000.0, ci.current());
68     }
69 }
70