]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.nativemem/src/org/simantics/nativemem/NativeMem.java
Allow tab-separated columnized logging of memory use
[simantics/platform.git] / bundles / org.simantics.nativemem / src / org / simantics / nativemem / NativeMem.java
1 /*******************************************************************************
2  * Copyright (c) 2016, 2017 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     Semantum Oy - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.nativemem;
13
14 import java.lang.reflect.InvocationTargetException;
15
16 import org.simantics.nativemem.internal.Arch;
17 import org.simantics.nativemem.internal.DummyProcessMemoryInfo;
18 import org.simantics.nativemem.internal.CMemoryInfo;
19 import org.simantics.nativemem.internal.OS;
20 import org.simantics.nativemem.internal.Resource;
21 import org.simantics.nativemem.internal.Resource32;
22 import org.simantics.nativemem.internal.Resource64;
23 import org.simantics.nativemem.internal.linux.Stat;
24 import org.simantics.nativemem.internal.win.ProcessMemoryCounters;
25 import org.simantics.nativemem.internal.win.Psapi32;
26 import org.simantics.nativemem.internal.win.Psapi64;
27
28 import com.sun.jna.platform.win32.Kernel32;
29 import com.sun.jna.platform.win32.WinNT.HANDLE;
30
31 /**
32  * @author Tuukka Lehtonen
33  */
34 public class NativeMem {
35
36     /**
37      * @param out
38      *            the structure to write the result into or <code>null</code> to
39      *            create a new structure
40      * @return the result structure
41      */
42     public static ProcessMemoryInfo getMemoryInfo(ProcessMemoryInfo out) {
43         switch (OS.calculate()) {
44         case WINDOWS:
45             return getProcessMemoryCounters(out);
46
47         case APPLE:
48             return getCMemoryInfo(out);
49
50         case LINUX: {
51             CMemoryInfo info = getCMemoryInfo(out);
52             info.peakRSS *= 1024L;
53             getCurrentRSS(info);
54             return info;
55         }
56
57         default:
58             return DummyProcessMemoryInfo.INSTANCE;
59         }
60     }
61
62     private static ProcessMemoryCounters getProcessMemoryCounters(ProcessMemoryInfo out) {
63         ProcessMemoryCounters counters = castOrCreate(out, ProcessMemoryCounters.class);
64         HANDLE proc = Kernel32.INSTANCE.GetCurrentProcess();
65         switch (Arch.calculate()) {
66         case X86: {
67             Psapi32.PROCESS_MEMORY_COUNTERS_EX pmem = new Psapi32.PROCESS_MEMORY_COUNTERS_EX();
68             boolean ok = Psapi32.INSTANCE.GetProcessMemoryInfo(proc, pmem, pmem.size());
69             if (ok)
70                 pmem.writeTo(counters);
71             return counters;
72         }
73
74         case X86_64: {
75             Psapi64.PROCESS_MEMORY_COUNTERS_EX pmem = new Psapi64.PROCESS_MEMORY_COUNTERS_EX();
76             boolean ok = Psapi64.INSTANCE.GetProcessMemoryInfo(proc, pmem, pmem.size());
77             if (ok)
78                 pmem.writeTo(counters);
79             return counters;
80         }
81
82         default:
83             return counters;
84         }
85     }
86
87     private static CMemoryInfo getCMemoryInfo(ProcessMemoryInfo out) {
88         CMemoryInfo info = castOrCreate(out, CMemoryInfo.class);
89
90         switch (Arch.calculate()) {
91         case X86: {
92             Resource32.Rusage rusage = new Resource32.Rusage();
93             int ok = Resource32.INSTANCE.getrusage(Resource.RUSAGE_SELF, rusage);
94             if (ok == 0)
95                 rusage.writeTo(info);
96             return info;
97         }
98
99         case X86_64: {
100             Resource64.Rusage rusage = new Resource64.Rusage();
101             int ok = Resource64.INSTANCE.getrusage(Resource.RUSAGE_SELF, rusage);
102             if (ok == 0)
103                 rusage.writeTo(info);
104             return info;
105         }
106
107         default:
108             return info;
109         }
110     }
111
112     private static CMemoryInfo getCurrentRSS(ProcessMemoryInfo out) {
113         CMemoryInfo info = castOrCreate(out, CMemoryInfo.class);
114
115         switch (Arch.calculate()) {
116         case X86: {
117             long rss = Stat.getCurrentRSS(Resource32.INSTANCE);
118             if (rss >= 0)
119                 info.currentRSS = rss;
120             return info;
121         }
122
123         case X86_64: {
124             long rss = Stat.getCurrentRSS(Resource64.INSTANCE);
125             if (rss >= 0)
126                 info.currentRSS = rss;
127             return info;
128         }
129
130         default:
131             return info;
132         }
133     }
134
135     private static <T> T castOrCreate(Object o, Class<T> clazz) {
136         if (clazz.isInstance(o))
137             return clazz.cast(o);
138         try {
139             return clazz.getConstructor().newInstance();
140         } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
141                 | NoSuchMethodException | SecurityException e) {
142             throw new Error("Class " + clazz + " does not have a public parameterless constructor", e);
143         }
144     }
145
146 }