X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fbin%2FMemorySetting.java;fp=src%2Fjalview%2Fbin%2FMemorySetting.java;h=f6924b9b9cdfb6369288aaaee05f48efe8acd918;hb=0769864c9c613841b08ee3da43412d917631b539;hp=c8bc222890808346c967420c8aafa093960d1d47;hpb=2c5026c454594e7299a58b57fe0df3aa563c8d8b;p=jalview.git diff --git a/src/jalview/bin/MemorySetting.java b/src/jalview/bin/MemorySetting.java index c8bc222..f6924b9 100644 --- a/src/jalview/bin/MemorySetting.java +++ b/src/jalview/bin/MemorySetting.java @@ -1,51 +1,222 @@ package jalview.bin; -import java.lang.management.ManagementFactory; -import java.lang.management.OperatingSystemMXBean; - public class MemorySetting { public static final long leaveFreeMinMemory = 536870912; // 0.5 GB public static final long applicationMinMemory = 536870912; // 0.5 GB - protected static long getPhysicalMemory() + private final static int maxHeapSizePerCentDefault = 90; + + public final static String maxHeapSizePerCentProperty = "jvmmempc"; + + private final static long maxHeapSizeDefault = 34359738368L; // 32GB + + private final static long noMemMaxHeapSizeDefault = 8589934592L; // 8GB + + public final static String maxHeapSizeProperty = "jvmmemmax"; + + protected static boolean logToClassChecked = false; + + public static long getMemorySetting() { - final OperatingSystemMXBean o = ManagementFactory - .getOperatingSystemMXBean(); + return getMemorySetting(null, null); + } + + public static long getMemorySetting(String jvmmemmaxorig, + String jvmmempcorig) + { + // actual Xmx value-to-be + long maxMemLong = -1; + // get (absolute) jvmmaxmem setting + long memmax = maxHeapSizeDefault; + if (jvmmemmaxorig == null) + { + jvmmemmaxorig = System.getProperty(maxHeapSizeProperty); + } + String jvmmemmax = jvmmemmaxorig; + if (jvmmemmax != null && jvmmemmax.length() > 0) + { + long multiplier = 1; + switch (jvmmemmax.toLowerCase().substring(jvmmemmax.length() - 1)) + { + case "t": + multiplier = 1099511627776L; // 2^40 + jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1); + break; + case "g": + multiplier = 1073741824; // 2^30 + jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1); + break; + case "m": + multiplier = 1048576; // 2^20 + jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1); + break; + case "k": + multiplier = 1024; // 2^10 + jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1); + break; + case "b": + multiplier = 1; // 2^0 + jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1); + break; + default: + break; + } + + // parse the arg + try + { + memmax = Long.parseLong(jvmmemmax); + } catch (NumberFormatException e) + { + memmax = maxHeapSizeDefault; + System.out.println("MemorySetting Property '" + + maxHeapSizeProperty + + "' (" + + jvmmemmaxorig + "') badly formatted, using default (" + + memmax + ")."); + } + + // apply multiplier if not too big (i.e. bigger than a long) + if (Long.MAX_VALUE / memmax < multiplier) + { + memmax = maxHeapSizeDefault; + System.out.println( + "MemorySetting Property '" + maxHeapSizeProperty + "' (" + + jvmmemmaxorig + + ") too big, using default (" + memmax + ")."); + } + else + { + memmax = multiplier * memmax; + } + + // check at least minimum value (this accounts for negatives too) + if (memmax < applicationMinMemory) + { + memmax = applicationMinMemory; + System.out.println( + "MemorySetting Property '" + maxHeapSizeProperty + "' (" + + jvmmemmaxorig + + ") too small, using minimum (" + + applicationMinMemory + ")."); + } + + } + else + { + // no need to warn if no setting + // System.out.println("MemorySetting Property '" + maxHeapSizeProperty + // + "' not + // set."); + } + + // get max percent of physical memory + float percent = maxHeapSizePerCentDefault; + if (jvmmempcorig == null) + { + jvmmempcorig = System.getProperty(maxHeapSizePerCentProperty); + } + String jvmmempc = jvmmempcorig; + if (jvmmempc == null) + { + jvmmempc = System.getProperty(maxHeapSizePerCentProperty); + } + long pcmem = -1; try { - if (o instanceof com.sun.management.OperatingSystemMXBean) + if (jvmmempc != null) { - final com.sun.management.OperatingSystemMXBean osb = (com.sun.management.OperatingSystemMXBean) o; - return osb.getTotalPhysicalMemorySize(); + float trypercent = Float.parseFloat(jvmmempc); + if (0 < trypercent && trypercent <= 100f) + { + percent = trypercent; + } + else + { + System.out.println( + "MemorySetting Property '" + maxHeapSizePerCentProperty + + "' should be in range 1..100"); + } } - } catch (NoClassDefFoundError e) + } catch (NumberFormatException e) { - // com.sun.management.OperatingSystemMXBean doesn't exist in this JVM - Cache.log.error("No com.sun.management.OperatingSystemMXBean"); + System.out.println( + "MemorySetting property '" + maxHeapSizePerCentProperty + + "' (" + jvmmempc + ") badly formatted"); } - // We didn't get a com.sun.management.OperatingSystemMXBean. - return -1; - } + // catch everything in case of no com.sun.management.OperatingSystemMXBean + boolean memoryPercentError = false; + try + { + long physicalMem = MemoryPercent.getPhysicalMemory(); + if (physicalMem > applicationMinMemory) + { + // try and set at least applicationMinMemory and thereafter ensure + // leaveFreeMinMemory is left for the OS - public static long memPercent(int percent) - { - long memPercent = -1; + pcmem = (long) ((physicalMem * percent) / 100F); + + // check for memory left for OS + if (physicalMem - pcmem < leaveFreeMinMemory) + { + pcmem = physicalMem - leaveFreeMinMemory; + System.out.println("MemorySetting Property '" + + maxHeapSizePerCentProperty + "' (" + jvmmempcorig + + ") too large. Leaving free space for OS, using (" + + pcmem + ")."); + } - long physicalMem = getPhysicalMemory(); - if (physicalMem > applicationMinMemory) + // check for minimum application memsize + if (pcmem < applicationMinMemory) + { + pcmem = applicationMinMemory; + System.out.println("MemorySetting Property '" + + maxHeapSizePerCentProperty + "' (" + jvmmempcorig + + ") too small, using minimum (" + applicationMinMemory + + ")."); + } + } + else + { + // not enough memory for application, just try and grab what we can! + pcmem = physicalMem; + System.out.println("MemorySetting Property '" + + maxHeapSizePerCentProperty + "' (" + jvmmempcorig + + "): Not enough memory, using max available (" + pcmem + + ")."); + } + + } catch (Throwable t) + { + memoryPercentError = true; + System.out.println("Problem calling MemoryPercent.memPercent(" + + percent + + "). Likely to be problem with com.sun.management.OperatingSystemMXBean"); + t.printStackTrace(); + } + // In the case of an error reading the percentage of physical memory (when jvmmempc was set), let's cap maxMemLong to 8GB + if (memoryPercentError && jvmmempc != null && pcmem == -1 + && memmax > noMemMaxHeapSizeDefault) + { + System.out.println( + "Capping maximum memory to 8GB due to failure to read physical memory size."); + memmax = noMemMaxHeapSizeDefault; + } + + if (pcmem == -1) // not set + { + maxMemLong = memmax; + } + else { - // try and set at least applicationMinMemory and thereafter ensure - // leaveFreeMinMemory is left for the OS - memPercent = Math.max(applicationMinMemory, - physicalMem - Math.max(physicalMem * (100 - percent) / 100, - leaveFreeMinMemory)); + maxMemLong = Math.min(pcmem, memmax); } - return memPercent; + return maxMemLong; } -} +} \ No newline at end of file