ac1ac28067870be8e0d6a7a8ba76d5dd6f07ef53
[jalview.git] / src / jalview / bin / MemorySetting.java
1 package jalview.bin;
2
3 public class MemorySetting
4 {
5   public static final long leaveFreeMinMemory = 536870912; // 0.5 GB
6
7   public static final long applicationMinMemory = 536870912; // 0.5 GB
8
9   private final static int maxHeapSizePerCentDefault = 90;
10
11   public final static String maxHeapSizePerCentProperty = "jvmmempc";
12
13   private final static long maxHeapSizeDefault = 34359738368L; // 32GB
14
15   private final static long noMemMaxHeapSizeDefault = 8589934592L; // 8GB
16
17   public final static String maxHeapSizeProperty = "jvmmemmax";
18
19   public static long getMemorySetting()
20   {
21     return getMemorySetting(null, null);
22   }
23
24   public static long getMemorySetting(String jvmmemmaxString,
25           String jvmmempcString)
26   {
27     // actual Xmx value-to-be
28     long maxMemLong = -1;
29
30     // get (absolute) jvmmaxmem setting
31     long memmax = maxHeapSizeDefault;
32     String jvmmemmaxorig = jvmmemmaxString;
33     if (jvmmemmaxorig == null)
34     {
35       jvmmemmaxorig = System.getProperty(maxHeapSizeProperty);
36     }
37     String jvmmemmax = jvmmemmaxorig;
38     if (jvmmemmax != null && jvmmemmax.length() > 0)
39     {
40       long multiplier = 1;
41       switch (jvmmemmax.toLowerCase().substring(jvmmemmax.length() - 1))
42       {
43       case "t":
44         multiplier = 1099511627776L; // 2^40
45         jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
46         break;
47       case "g":
48         multiplier = 1073741824; // 2^30
49         jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
50         break;
51       case "m":
52         multiplier = 1048576; // 2^20
53         jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
54         break;
55       case "k":
56         multiplier = 1024; // 2^10
57         jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
58         break;
59       case "b":
60         multiplier = 1; // 2^0
61         jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
62         break;
63       default:
64         break;
65       }
66
67       // parse the arg
68       try
69       {
70         memmax = Long.parseLong(jvmmemmax);
71       } catch (NumberFormatException e)
72       {
73         memmax = maxHeapSizeDefault;
74         System.out.println("MemorySetting Property '" + maxHeapSizeProperty
75                 + "' ("
76                 + jvmmemmaxorig + "') badly formatted, using default ("
77                 + memmax + ").");
78       }
79
80       // apply multiplier if not too big (i.e. bigger than a long)
81       if (Long.MAX_VALUE / memmax < multiplier)
82       {
83         memmax = maxHeapSizeDefault;
84         System.out.println(
85                 "MemorySetting Property '" + maxHeapSizeProperty + "' ("
86                         + jvmmemmaxorig
87                         + ") too big, using default (" + memmax + ").");
88       }
89       else
90       {
91         memmax = multiplier * memmax;
92       }
93
94       // check at least minimum value (this accounts for negatives too)
95       if (memmax < MemorySetting.applicationMinMemory)
96       {
97         memmax = MemorySetting.applicationMinMemory;
98         System.out.println(
99                 "MemorySetting Property '" + maxHeapSizeProperty + "' ("
100                         + jvmmemmaxorig
101                         + ") too small, using minimum (" + memmax + ").");
102       }
103
104     }
105     else
106     {
107       // no need to warn if no setting
108       // System.out.println("MemorySetting Property '" + maxHeapSizeProperty + "' not
109       // set.");
110     }
111
112     // get max percent of physical memory
113     float percent = maxHeapSizePerCentDefault;
114     String jvmmempc = jvmmempcString;
115     if (jvmmempc == null)
116     {
117       jvmmempc = System.getProperty(maxHeapSizePerCentProperty);
118     }
119     long pcmem = -1;
120     try
121     {
122       if (jvmmempc != null)
123       {
124         float trypercent = Float.parseFloat(jvmmempc);
125         if (0 < trypercent && trypercent <= 100f)
126         {
127           percent = trypercent;
128         }
129         else
130         {
131           System.out.println(
132                   "MemorySetting Property '" + maxHeapSizePerCentProperty
133                   + "' should be in range 1..100");
134         }
135       }
136     } catch (NumberFormatException e)
137     {
138       System.out.println(
139               "MemorySetting property '" + maxHeapSizePerCentProperty
140                       + "' (" + jvmmempc + ") badly formatted");
141     }
142
143     // catch everything in case of no com.sun.management.OperatingSystemMXBean
144     boolean memoryPercentError = false;
145     try
146     {
147       pcmem = MemoryPercent.memPercent(percent);
148     } catch (Throwable t)
149     {
150       memoryPercentError = true;
151       System.out.println("Problem calling MemoryPercent.memPercent("
152               + percent
153               + "). Likely to be problem with com.sun.management.OperatingSystemMXBean");
154       t.printStackTrace();
155     }
156     // In the case of an error reading the percentage if physical memory, let's cap maxMemLong to 8GB
157     if (memoryPercentError && jvmmempc != null && pcmem == -1
158             && memmax > noMemMaxHeapSizeDefault)
159     {
160       System.out.println(
161               "Capping maximum memory to 8GB due to failure to read physical memory size.");
162       memmax = noMemMaxHeapSizeDefault;
163     }
164
165     if (pcmem == -1) // not set
166     {
167       maxMemLong = memmax;
168     }
169     else
170     {
171       maxMemLong = Math.min(pcmem, memmax);
172     }
173
174     return maxMemLong;
175   }
176
177 }