1 | package de.botcompany; |
2 | |
3 | import java.util.*; |
4 | import java.util.regex.*; |
5 | import java.io.*; |
6 | import java.net.*; |
7 | import java.lang.management.*; |
8 | |
9 | public class LinuxProcessSizeDetector { |
10 | public static void main(String[] args) throws IOException { |
11 | rssFixedForZGC_verbose = true; |
12 | if (args.length == 0) |
13 | System.out.println("RSS of this process: " + rssFixedForZGC()); |
14 | else { |
15 | int pid = Integer.parseInt(args[0]); |
16 | System.out.println("RSS of process " + pid + ": " + rssFixedForZGC(pid)); |
17 | } |
18 | } |
19 | |
20 | static boolean rssFixedForZGC_verbose = false; |
21 | |
22 | // get corrected RSS for this process |
23 | public static long rssFixedForZGC() throws IOException { |
24 | return rssFixedForZGC(processID_int()); |
25 | } |
26 | |
27 | // get corrected RSS for another process |
28 | public static long rssFixedForZGC(int pid) throws IOException { |
29 | //if (!is64BitLinux()) fail("Not on 64 Bit Linux"); |
30 | String range = null; |
31 | TreeMap<String, Long> rssByRange = new TreeMap(); |
32 | Pattern patAddr = Pattern.compile("^([0-9a-f]{1,16})-"); |
33 | BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/" + pid + "/smaps"))); |
34 | try { |
35 | String s; |
36 | while ((s = in.readLine()) != null) { |
37 | Matcher m = patAddr.matcher(s); |
38 | String addr = m.find() ? m.group(1) : null; |
39 | if (addr != null) { |
40 | //print("Have address: " + addr); |
41 | String cleanedAddr = longToHex(parseUnsignedHexLong(addr) & ~((1L << 42) - 1)); |
42 | range = takeFirst_string(6, cleanedAddr); |
43 | continue; |
44 | } |
45 | // else print("Not range: " + s); |
46 | String[] p = parseColonProperty_array(s); |
47 | if (p != null && eqic(p[0], "rss")) { |
48 | long size = Long.parseLong(beforeSpace(p[1])); |
49 | if (size != 0) |
50 | rssByRange.put(range, getOrCreate_long(rssByRange, range) + size); |
51 | } |
52 | } |
53 | if (rssFixedForZGC_verbose) |
54 | for (Map.Entry<String, Long> e : rssByRange.entrySet()) { |
55 | System.out.println("Address range " + rpad(e.getKey(), 16, 'x') + ": " + toK(e.getValue()) + " MB"); |
56 | } |
57 | Long min = null; |
58 | for (String _range : ll("000004", "000008", "000010")) { |
59 | Long l = rssByRange.get(_range); |
60 | if (l != null) |
61 | min = min == null ? l : Math.min(min, l); |
62 | } |
63 | long total = 0; |
64 | for (long l : rssByRange.values()) total += l; |
65 | long guess = min == null ? total : total - min * 3; |
66 | return guess * 1024; |
67 | } finally { |
68 | _close(in); |
69 | } |
70 | } |
71 | |
72 | // current process ID |
73 | static int processID_int() { |
74 | return parseInt(getPID()); |
75 | } |
76 | |
77 | static String longToHex(long l) { |
78 | return bytesToHex(longToBytes(l)); |
79 | } |
80 | |
81 | static long parseUnsignedHexLong(String s) { |
82 | // from Java 8 |
83 | return Long.parseUnsignedLong(s, 16); |
84 | } |
85 | |
86 | static String takeFirst_string(int n, String s) { |
87 | return substring(s, 0, n); |
88 | } |
89 | |
90 | static String takeFirst_string(String s, int n) { |
91 | return substring(s, 0, n); |
92 | } |
93 | |
94 | static String[] parseColonProperty_array(String s) { |
95 | if (s == null) |
96 | return null; |
97 | int i = s.indexOf(':'); |
98 | if (i < 0) |
99 | return null; |
100 | return new String[] { trimSubstring(s, 0, i), trimSubstring(s, i + 1) }; |
101 | } |
102 | |
103 | static boolean eqic(String a, String b) { |
104 | if ((a == null) != (b == null)) |
105 | return false; |
106 | if (a == null) |
107 | return true; |
108 | return a.equalsIgnoreCase(b); |
109 | } |
110 | |
111 | static boolean eqic(char a, char b) { |
112 | if (a == b) |
113 | return true; |
114 | char u1 = Character.toUpperCase(a); |
115 | char u2 = Character.toUpperCase(b); |
116 | if (u1 == u2) |
117 | return true; |
118 | return Character.toLowerCase(u1) == Character.toLowerCase(u2); |
119 | } |
120 | |
121 | static String beforeSpace(String s) { |
122 | return onlyUntilSpace(s); |
123 | } |
124 | |
125 | static <A> long getOrCreate_long(Map<A, Long> map, A key) { |
126 | Long b = map.get(key); |
127 | if (b == null) |
128 | map.put(key, b = 0L); |
129 | return b; |
130 | } |
131 | |
132 | static String rpad(String s, int l) { |
133 | return rpad(s, l, ' '); |
134 | } |
135 | |
136 | static String rpad(String s, int l, char c) { |
137 | return lengthOfString(s) >= l ? s : s + rep(c, l - lengthOfString(s)); |
138 | } |
139 | |
140 | static String rpad(int l, String s) { |
141 | return rpad(s, l); |
142 | } |
143 | |
144 | static long toK(long l) { |
145 | return (l + 1023) / 1024; |
146 | } |
147 | |
148 | static <A> List<A> ll(A... a) { |
149 | ArrayList l = new ArrayList(a.length); |
150 | if (a != null) |
151 | for (A x : a) l.add(x); |
152 | return l; |
153 | } |
154 | |
155 | static void _close(AutoCloseable c) { |
156 | if (c != null) |
157 | try { |
158 | c.close(); |
159 | } catch (Throwable e) { |
160 | // Some classes stupidly throw an exception on double-closing |
161 | if (c instanceof javax.imageio.stream.ImageOutputStream) |
162 | return; |
163 | else |
164 | throw rethrow(e); |
165 | } |
166 | } |
167 | |
168 | static int parseInt(String s) { |
169 | return emptyString(s) ? 0 : Integer.parseInt(s); |
170 | } |
171 | |
172 | static int parseInt(char c) { |
173 | return Integer.parseInt(str(c)); |
174 | } |
175 | |
176 | static String processID_cached; |
177 | |
178 | // try to get our current process ID |
179 | static String getPID() { |
180 | if (processID_cached == null) { |
181 | String name = ManagementFactory.getRuntimeMXBean().getName(); |
182 | processID_cached = name.replaceAll("@.*", ""); |
183 | } |
184 | return processID_cached; |
185 | } |
186 | |
187 | public static String bytesToHex(byte[] bytes) { |
188 | return bytesToHex(bytes, 0, bytes.length); |
189 | } |
190 | |
191 | public static String bytesToHex(byte[] bytes, int ofs, int len) { |
192 | StringBuilder stringBuilder = new StringBuilder(len * 2); |
193 | for (int i = 0; i < len; i++) { |
194 | String s = "0" + Integer.toHexString(bytes[ofs + i]); |
195 | stringBuilder.append(s.substring(s.length() - 2, s.length())); |
196 | } |
197 | return stringBuilder.toString(); |
198 | } |
199 | |
200 | static byte[] longToBytes(long l) { |
201 | return new byte[] { (byte) (l >>> 56), (byte) (l >>> 48), (byte) (l >>> 40), (byte) (l >>> 32), (byte) (l >>> 24), (byte) (l >>> 16), (byte) (l >>> 8), (byte) l }; |
202 | } |
203 | |
204 | static String substring(String s, int x) { |
205 | return substring(s, x, strL(s)); |
206 | } |
207 | |
208 | static String substring(String s, int x, int y) { |
209 | if (s == null) |
210 | return null; |
211 | if (x < 0) |
212 | x = 0; |
213 | if (x >= s.length()) |
214 | return ""; |
215 | if (y < x) |
216 | y = x; |
217 | if (y > s.length()) |
218 | y = s.length(); |
219 | return s.substring(x, y); |
220 | } |
221 | |
222 | static String trimSubstring(String s, int x) { |
223 | return trim(substring(s, x)); |
224 | } |
225 | |
226 | static String trimSubstring(String s, int x, int y) { |
227 | return trim(substring(s, x, y)); |
228 | } |
229 | |
230 | static boolean eq(Object a, Object b) { |
231 | return a == b || (a == null ? b == null : b != null && a.equals(b)); |
232 | } |
233 | |
234 | static String asString(Object o) { |
235 | return o == null ? null : o.toString(); |
236 | } |
237 | |
238 | static String onlyUntilSpace(String s) { |
239 | int i = s.indexOf(' '); |
240 | return i >= 0 ? s.substring(0, i) : s; |
241 | } |
242 | |
243 | static int lengthOfString(String s) { |
244 | return s == null ? 0 : s.length(); |
245 | } |
246 | |
247 | static String rep(int n, char c) { |
248 | return repeat(c, n); |
249 | } |
250 | |
251 | static String rep(char c, int n) { |
252 | return repeat(c, n); |
253 | } |
254 | |
255 | static <A> List<A> rep(A a, int n) { |
256 | return repeat(a, n); |
257 | } |
258 | |
259 | static <A> List<A> rep(int n, A a) { |
260 | return repeat(n, a); |
261 | } |
262 | |
263 | static RuntimeException rethrow(Throwable t) { |
264 | throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); |
265 | } |
266 | |
267 | static RuntimeException rethrow(String msg, Throwable t) { |
268 | throw new RuntimeException(msg, t); |
269 | } |
270 | |
271 | static boolean emptyString(String s) { |
272 | return s == null || s.length() == 0; |
273 | } |
274 | |
275 | static String str(Object o) { |
276 | return o == null ? "null" : o.toString(); |
277 | } |
278 | |
279 | static String str(char[] c) { |
280 | return new String(c); |
281 | } |
282 | |
283 | static int strL(String s) { |
284 | return s == null ? 0 : s.length(); |
285 | } |
286 | |
287 | static String trim(String s) { |
288 | return s == null ? null : s.trim(); |
289 | } |
290 | |
291 | static String trim(StringBuilder buf) { |
292 | return buf.toString().trim(); |
293 | } |
294 | |
295 | static String trim(StringBuffer buf) { |
296 | return buf.toString().trim(); |
297 | } |
298 | |
299 | static String repeat(char c, int n) { |
300 | n = Math.max(n, 0); |
301 | char[] chars = new char[n]; |
302 | for (int i = 0; i < n; i++) chars[i] = c; |
303 | return new String(chars); |
304 | } |
305 | |
306 | static <A> List<A> repeat(A a, int n) { |
307 | n = Math.max(n, 0); |
308 | List<A> l = new ArrayList(n); |
309 | for (int i = 0; i < n; i++) l.add(a); |
310 | return l; |
311 | } |
312 | |
313 | static <A> List<A> repeat(int n, A a) { |
314 | return repeat(a, n); |
315 | } |
316 | } |
Began life as a copy of #1025551
Travelled to 6 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1025555 |
Snippet name: | LinuxProcessSizeDetector (pure Java) |
Eternal ID of this version: | #1025555/14 |
Text MD5: | c72aafba2e4de06a235d7537ae8f46a3 |
Author: | stefan |
Category: | javax |
Type: | Java source code |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2019-10-03 14:01:15 |
Source code size: | 8532 bytes / 316 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 222 / 117 |
Version history: | 13 change(s) |
Referenced in: | [show references] |