JAL-3407 release notes for JAL-3449 JAL-3393 JAL-3420 JAL-3477 JAL-3447 JAL-3542
[jalview.git] / getdown / src / getdown / core / src / main / java / 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   protected static boolean logToClassChecked = false;
20
21   public static long getMemorySetting()
22   {
23     return getMemorySetting(null, null);
24   }
25
26   public static long getMemorySetting(String jvmmemmaxorig,
27           String jvmmempcorig)
28   {
29     // actual Xmx value-to-be
30     long maxMemLong = -1;
31
32     // get (absolute) jvmmaxmem setting
33     long memmax = maxHeapSizeDefault;
34     if (jvmmemmaxorig == null)
35     {
36       jvmmemmaxorig = System.getProperty(maxHeapSizeProperty);
37     }
38     String jvmmemmax = jvmmemmaxorig;
39     if (jvmmemmax != null && jvmmemmax.length() > 0)
40     {
41       long multiplier = 1;
42       switch (jvmmemmax.toLowerCase().substring(jvmmemmax.length() - 1))
43       {
44       case "t":
45         multiplier = 1099511627776L; // 2^40
46         jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
47         break;
48       case "g":
49         multiplier = 1073741824; // 2^30
50         jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
51         break;
52       case "m":
53         multiplier = 1048576; // 2^20
54         jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
55         break;
56       case "k":
57         multiplier = 1024; // 2^10
58         jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
59         break;
60       case "b":
61         multiplier = 1; // 2^0
62         jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
63         break;
64       default:
65         break;
66       }
67
68       // parse the arg
69       try
70       {
71         memmax = Long.parseLong(jvmmemmax);
72       } catch (NumberFormatException e)
73       {
74         memmax = maxHeapSizeDefault;
75         System.out.println("MemorySetting Property '"
76                 + maxHeapSizeProperty
77                 + "' ("
78                 + jvmmemmaxorig + "') badly formatted, using default ("
79                 + memmax + ").");
80       }
81
82       // apply multiplier if not too big (i.e. bigger than a long)
83       if (Long.MAX_VALUE / memmax < multiplier)
84       {
85         memmax = maxHeapSizeDefault;
86         System.out.println(
87                 "MemorySetting Property '" + maxHeapSizeProperty + "' ("
88                         + jvmmemmaxorig
89                         + ") too big, using default (" + memmax + ").");
90       }
91       else
92       {
93         memmax = multiplier * memmax;
94       }
95
96       // check at least minimum value (this accounts for negatives too)
97       if (memmax < applicationMinMemory)
98       {
99         memmax = applicationMinMemory;
100         System.out.println(
101                 "MemorySetting Property '" + maxHeapSizeProperty + "' ("
102                         + jvmmemmaxorig
103                         + ") too small, using minimum ("
104                         + applicationMinMemory + ").");
105       }
106
107     }
108     else
109     {
110       // no need to warn if no setting
111       // System.out.println("MemorySetting Property '" + maxHeapSizeProperty
112       // + "' not
113       // set.");
114     }
115
116     // get max percent of physical memory
117     float percent = maxHeapSizePerCentDefault;
118     if (jvmmempcorig == null)
119     {
120       jvmmempcorig = System.getProperty(maxHeapSizePerCentProperty);
121     }
122     String jvmmempc = jvmmempcorig;
123     if (jvmmempc == null)
124     {
125       jvmmempc = System.getProperty(maxHeapSizePerCentProperty);
126     }
127     long pcmem = -1;
128     try
129     {
130       if (jvmmempc != null)
131       {
132         float trypercent = Float.parseFloat(jvmmempc);
133         if (0 < trypercent && trypercent <= 100f)
134         {
135           percent = trypercent;
136         }
137         else
138         {
139           System.out.println(
140                   "MemorySetting Property '" + maxHeapSizePerCentProperty
141                   + "' should be in range 1..100");
142         }
143       }
144     } catch (NumberFormatException e)
145     {
146       System.out.println(
147               "MemorySetting property '" + maxHeapSizePerCentProperty
148                       + "' (" + jvmmempc + ") badly formatted");
149     }
150
151     // catch everything in case of no com.sun.management.OperatingSystemMXBean
152     boolean memoryPercentError = false;
153     try
154     {
155       long physicalMem = MemoryPercent.getPhysicalMemory();
156       if (physicalMem > applicationMinMemory)
157       {
158         // try and set at least applicationMinMemory and thereafter ensure
159         // leaveFreeMinMemory is left for the OS
160
161         pcmem = (long) ((physicalMem * percent) / 100F);
162
163         // check for memory left for OS
164         if (physicalMem - pcmem < leaveFreeMinMemory)
165         {
166           pcmem = physicalMem - leaveFreeMinMemory;
167           System.out.println("MemorySetting Property '"
168                   + maxHeapSizePerCentProperty + "' (" + jvmmempcorig
169                   + ") too large. Leaving free space for OS, using ("
170                   + pcmem + ").");
171         }
172
173         // check for minimum application memsize
174         if (pcmem < applicationMinMemory)
175         {
176           pcmem = applicationMinMemory;
177           System.out.println("MemorySetting Property '"
178                   + maxHeapSizePerCentProperty + "' (" + jvmmempcorig
179                   + ") too small, using minimum (" + applicationMinMemory
180                   + ").");
181         }
182       }
183       else
184       {
185         // not enough memory for application, just try and grab what we can!
186         pcmem = physicalMem;
187         System.out.println("MemorySetting Property '"
188                 + maxHeapSizePerCentProperty + "' (" + jvmmempcorig
189                 + "): Not enough memory, using max available (" + pcmem
190                 + ").");
191       }
192
193     } catch (Throwable t)
194     {
195       memoryPercentError = true;
196       System.out.println("Problem calling MemoryPercent.memPercent("
197               + percent
198               + "). Likely to be problem with com.sun.management.OperatingSystemMXBean");
199       t.printStackTrace();
200     }
201     // In the case of an error reading the percentage of physical memory (when jvmmempc was set), let's cap maxMemLong to 8GB
202     if (memoryPercentError && jvmmempc != null && pcmem == -1
203             && memmax > noMemMaxHeapSizeDefault)
204     {
205       System.out.println(
206               "Capping maximum memory to 8GB due to failure to read physical memory size.");
207       memmax = noMemMaxHeapSizeDefault;
208     }
209
210     if (pcmem == -1) // not set
211     {
212       maxMemLong = memmax;
213     }
214     else
215     {
216       maxMemLong = Math.min(pcmem, memmax);
217     }
218
219     return maxMemLong;
220   }
221
222 }