4 * Methods to decide on appropriate memory setting for Jalview based on two
5 * optionally provided values: jvmmempc - the maximum percentage of total
6 * physical memory to allocate, and jvmmemmax - the maximum absolute amount of
7 * physical memory to allocate. These can be provided as arguments or system
8 * properties. Other considerations such as minimum application requirements and
9 * leaving space for OS are used too.
14 public class MemorySetting
16 public static final long leaveFreeMinMemory = 536870912; // 0.5 GB
18 public static final long applicationMinMemory = 536870912; // 0.5 GB
20 private final static int maxHeapSizePerCentDefault = 90;
22 public final static String maxHeapSizePerCentPropertyName = "jvmmempc";
24 private final static long maxHeapSizeDefault = 34359738368L; // 32GB
26 private final static long noMemMaxHeapSizeDefault = 8589934592L; // 8GB
28 public final static String maxHeapSizePropertyName = "jvmmemmax";
30 protected static boolean logToClassChecked = false;
32 public static long getMemorySetting()
34 return getMemorySetting(null, null);
38 * Decide on appropriate memory setting for Jalview based on the two arguments
39 * values: jvmmempc - the maximum percentage of total physical memory to
40 * allocate, and jvmmemmax - the maximum absolute amount of physical memory to
41 * allocate. These can be provided as arguments. If not provided as arguments
42 * (or set as null) system properties will be used instead (if set). The memory
43 * setting returned will be the lower of the two values. If either of the values
44 * are not provided then defaults will be used (jvmmempc=90, jvmmemmax=32GB). If
45 * total physical memory can't be ascertained when jvmmempc was set or neither
46 * jvmmempc nor jvmmemmax were set, then jvmmemmax defaults to a much safer 8GB.
47 * In this case explicitly setting jvmmemmax and not setting jvmmempc can set a
48 * higher memory for Jalview. The calculation also tries to ensure 0.5GB memory
49 * for the OS, but also tries to ensure at least 0.5GB memory for Jalview (which
50 * takes priority over the OS) If there is less then 0.5GB of physical memory
51 * then the total physical memory is used for Jalview.
54 * Maximum value of memory to set. This can be a numeric
55 * string optionally followed by "b", "k", "m", "g", "t"
56 * (case insensitive) to indicate bytes, kilobytes,
57 * megabytes, gigabytes, terabytes respectively. If null a
58 * default value of 32G will be used. If null and either
59 * physical memory can't be determined then the default is
62 * Max percentage of physical memory to use. Defaults to
65 * @return The amount of memory (in bytes) to allocate to Jalview
67 public static long getMemorySetting(String jvmmemmaxarg,
70 // actual Xmx value-to-be
73 // (absolute) jvmmaxmem setting, start with default
74 long memmax = maxHeapSizeDefault;
75 if (jvmmemmaxarg == null)
77 jvmmemmaxarg = System.getProperty(maxHeapSizePropertyName);
79 String jvmmemmax = jvmmemmaxarg;
80 if (jvmmemmax != null && jvmmemmax.length() > 0)
83 switch (jvmmemmax.toLowerCase().substring(jvmmemmax.length() - 1))
86 multiplier = 1099511627776L; // 2^40
87 jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
90 multiplier = 1073741824; // 2^30
91 jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
94 multiplier = 1048576; // 2^20
95 jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
98 multiplier = 1024; // 2^10
99 jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
102 multiplier = 1; // 2^0
103 jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
112 memmax = Long.parseLong(jvmmemmax);
113 } catch (NumberFormatException e)
115 memmax = maxHeapSizeDefault;
116 System.out.println("MemorySetting Property '"
117 + maxHeapSizePropertyName
119 + jvmmemmaxarg + "') badly formatted, using default ("
123 // apply multiplier if not too big (i.e. bigger than a long)
124 if (Long.MAX_VALUE / memmax < multiplier)
126 memmax = maxHeapSizeDefault;
128 "MemorySetting Property '" + maxHeapSizePropertyName + "' ("
130 + ") too big, using default (" + memmax + ").");
134 memmax = multiplier * memmax;
137 // check at least minimum value (this accounts for negatives too)
138 if (memmax < applicationMinMemory)
140 memmax = applicationMinMemory;
142 "MemorySetting Property '" + maxHeapSizePropertyName + "' ("
144 + ") too small, using minimum ("
145 + applicationMinMemory + ").");
151 // no need to warn if no setting
152 // System.out.println("MemorySetting Property '" + maxHeapSizeProperty
157 // get max percent of physical memory, starting with default
158 float percent = maxHeapSizePerCentDefault;
159 if (jvmmempcarg == null)
161 jvmmempcarg = System.getProperty(maxHeapSizePerCentPropertyName);
163 String jvmmempc = jvmmempcarg;
167 if (jvmmempc != null)
169 float trypercent = Float.parseFloat(jvmmempc);
170 if (0 < trypercent && trypercent <= 100f)
172 percent = trypercent;
177 "MemorySetting Property '"
178 + maxHeapSizePerCentPropertyName
179 + "' should be in range 1..100. Using default "
183 } catch (NumberFormatException e)
186 "MemorySetting property '" + maxHeapSizePerCentPropertyName
187 + "' (" + jvmmempcarg + ") badly formatted");
190 // catch everything in case of no com.sun.management.OperatingSystemMXBean
191 boolean memoryPercentError = false;
194 long physicalMem = GetMemory.getPhysicalMemory();
195 if (physicalMem > applicationMinMemory)
197 // try and set at least applicationMinMemory and thereafter ensure
198 // leaveFreeMinMemory is left for the OS
200 mempc = (long) ((physicalMem / 100F) * percent);
202 // check for memory left for OS
203 boolean reducedmempc = false;
204 if (physicalMem - mempc < leaveFreeMinMemory)
206 mempc = physicalMem - leaveFreeMinMemory;
208 System.out.println("MemorySetting Property '"
209 + maxHeapSizePerCentPropertyName + "' (" + jvmmempcarg
210 + ") too large. Leaving free space for OS and reducing to ("
214 // check for minimum application memsize
215 if (mempc < applicationMinMemory)
219 System.out.println("Reduced MemorySetting (" + mempc
220 + ") too small. Increasing to application minimum ("
221 + applicationMinMemory + ").");
225 System.out.println("MemorySetting Property '"
226 + maxHeapSizePerCentPropertyName + "' (" + jvmmempcarg
227 + ") too small. Using minimum (" + applicationMinMemory
230 mempc = applicationMinMemory;
235 // not enough memory for application, just try and grab what we can!
238 "Not enough physical memory for application. Ignoring MemorySetting Property '"
239 + maxHeapSizePerCentPropertyName + "' ("
241 + "). Using maximum memory available ("
242 + physicalMem + ").");
245 } catch (Throwable t)
247 memoryPercentError = true;
249 "Problem calling GetMemory.getPhysicalMemory(). Likely to be problem with com.sun.management.OperatingSystemMXBean");
253 // In the case of an error reading the percentage of physical memory (when
254 // jvmmempc was set OR neither jvmmempc nor jvmmemmax were set), let's cap
256 if (memoryPercentError && mempc == -1
257 // && (jvmmempcarg != null || (jvmmempcarg == null && jvmmemmaxarg == null))
258 // the above is easier to understand but simplified to
259 && !(jvmmempcarg == null && jvmmemmaxarg != null)
260 && memmax > noMemMaxHeapSizeDefault)
263 "Capping maximum memory to "
264 + (noMemMaxHeapSizeDefault + 536870912) / 1073741824 // this is the nearest integer GB for noMemMaxHeapSizeDefault
265 + "GB due to failure to read physical memory size.");
266 memmax = noMemMaxHeapSizeDefault;
269 if (mempc == -1) // percentage memory not set
275 maxMemLong = Math.min(mempc, memmax);