blob: a2076eec520aa5d4caaf17f49690f3d3f395b399 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package com.google.devtools.build.lib.util;
16
17import static java.nio.charset.StandardCharsets.US_ASCII;
18
19import com.google.common.base.CharMatcher;
20import com.google.common.base.Splitter;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010021import com.google.common.io.Files;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010022import com.sun.management.OperatingSystemMXBean;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010023import java.io.File;
24import java.io.IOException;
25import java.lang.management.ManagementFactory;
26import java.lang.management.MemoryMXBean;
jhorvitz49cb5a62020-09-17 08:48:39 -070027import java.util.List;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010028
29/**
jhorvitz4fd8bbd2020-08-26 12:14:46 -070030 * Provides methods to measure the current resource usage of the current process. Also provides some
31 * convenience methods to obtain several system characteristics, like number of processors , total
32 * memory, etc.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010033 */
34public final class ResourceUsage {
35
36 /*
37 * Use com.sun.management.OperatingSystemMXBean instead of
38 * java.lang.management.OperatingSystemMXBean because the latter does not
39 * support getTotalPhysicalMemorySize() and getFreePhysicalMemorySize().
40 */
41 private static final OperatingSystemMXBean OS_BEAN =
42 (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
43
44 private static final MemoryMXBean MEM_BEAN = ManagementFactory.getMemoryMXBean();
Googlere92bfe52016-03-07 19:32:24 +000045 private static final Splitter WHITESPACE_SPLITTER = Splitter.on(CharMatcher.whitespace());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010046
jhorvitz4fd8bbd2020-08-26 12:14:46 -070047 private ResourceUsage() {}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010048
jhorvitz4fd8bbd2020-08-26 12:14:46 -070049 /** Returns the number of processors available to the Java virtual machine. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010050 public static int getAvailableProcessors() {
51 return OS_BEAN.getAvailableProcessors();
52 }
53
jhorvitz4fd8bbd2020-08-26 12:14:46 -070054 /** Returns the total physical memory in bytes. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010055 public static long getTotalPhysicalMemorySize() {
56 return OS_BEAN.getTotalPhysicalMemorySize();
57 }
58
jhorvitz4fd8bbd2020-08-26 12:14:46 -070059 /** Returns the operating system architecture. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010060 public static String getOsArchitecture() {
61 return OS_BEAN.getArch();
62 }
63
jhorvitz4fd8bbd2020-08-26 12:14:46 -070064 /** Returns the operating system name. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010065 public static String getOsName() {
66 return OS_BEAN.getName();
67 }
68
jhorvitz4fd8bbd2020-08-26 12:14:46 -070069 /** Returns the operating system version. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010070 public static String getOsVersion() {
71 return OS_BEAN.getVersion();
72 }
73
74 /**
75 * Returns the initial size of heap memory in bytes.
76 *
77 * @see MemoryMXBean#getHeapMemoryUsage()
78 */
79 public static long getHeapMemoryInit() {
80 return MEM_BEAN.getHeapMemoryUsage().getInit();
81 }
82
83 /**
84 * Returns the initial size of non heap memory in bytes.
85 *
86 * @see MemoryMXBean#getNonHeapMemoryUsage()
87 */
88 public static long getNonHeapMemoryInit() {
89 return MEM_BEAN.getNonHeapMemoryUsage().getInit();
90 }
91
92 /**
93 * Returns the maximum size of heap memory in bytes.
94 *
95 * @see MemoryMXBean#getHeapMemoryUsage()
96 */
97 public static long getHeapMemoryMax() {
98 return MEM_BEAN.getHeapMemoryUsage().getMax();
99 }
100
101 /**
102 * Returns the maximum size of non heap memory in bytes.
103 *
104 * @see MemoryMXBean#getNonHeapMemoryUsage()
105 */
106 public static long getNonHeapMemoryMax() {
107 return MEM_BEAN.getNonHeapMemoryUsage().getMax();
108 }
109
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700110 /** Returns a measurement of the current resource usage of the current process. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100111 public static Measurement measureCurrentResourceUsage() {
112 return measureCurrentResourceUsage("self");
113 }
114
115 /**
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700116 * Returns a measurement of the current resource usage of the process with the given process id.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100117 *
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700118 * @param processId the process id or <code>self</code> for the current process.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100119 */
120 public static Measurement measureCurrentResourceUsage(String processId) {
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700121 return new Measurement(
122 MEM_BEAN.getHeapMemoryUsage().getUsed(),
123 MEM_BEAN.getHeapMemoryUsage().getCommitted(),
124 MEM_BEAN.getNonHeapMemoryUsage().getUsed(),
125 MEM_BEAN.getNonHeapMemoryUsage().getCommitted(),
126 (float) OS_BEAN.getSystemLoadAverage(),
127 OS_BEAN.getFreePhysicalMemorySize(),
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100128 getCurrentCpuUtilizationInJiffies(processId));
129 }
130
131 /**
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700132 * Returns the current cpu utilization of the current process with the given id in jiffies. The
133 * returned array contains the following information: The 1st entry is the number of jiffies that
134 * the process has executed in user mode, and the 2nd entry is the number of jiffies that the
135 * process has executed in kernel mode. Reads /proc/self/stat to obtain this information.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100136 *
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700137 * @param processId the process id or <code>self</code> for the current process.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100138 */
139 private static long[] getCurrentCpuUtilizationInJiffies(String processId) {
140 try {
141 File file = new File("/proc/" + processId + "/stat");
142 if (file.isDirectory()) {
143 return new long[2];
144 }
jhorvitz49cb5a62020-09-17 08:48:39 -0700145 List<String> stat =
146 WHITESPACE_SPLITTER.splitToList(Files.asCharSource(file, US_ASCII).read());
147 if (stat.size() < 15) {
148 return new long[2]; // Tolerate malformed input.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100149 }
jhorvitz49cb5a62020-09-17 08:48:39 -0700150 return new long[] {Long.parseLong(stat.get(13)), Long.parseLong(stat.get(14))};
Ulf Adams07dba942015-03-05 14:47:37 +0000151 } catch (NumberFormatException | IOException e) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100152 return new long[2];
153 }
154 }
155
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700156 /** A snapshot of the resource usage of the current process at a point in time. */
157 public static final class Measurement {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100158
159 private final long timeInNanos;
160 private final long heapMemoryUsed;
161 private final long heapMemoryCommitted;
162 private final long nonHeapMemoryUsed;
163 private final long nonHeapMemoryCommitted;
164 private final float loadAverageLastMinute;
165 private final long freePhysicalMemory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100166 private final long[] cpuUtilizationInJiffies;
167
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700168 public Measurement(
169 long heapMemoryUsed,
170 long heapMemoryCommitted,
171 long nonHeapMemoryUsed,
172 long nonHeapMemoryCommitted,
173 float loadAverageLastMinute,
174 long freePhysicalMemory,
175 long[] cpuUtilizationInJiffies) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100176 super();
177 timeInNanos = System.nanoTime();
178 this.heapMemoryUsed = heapMemoryUsed;
179 this.heapMemoryCommitted = heapMemoryCommitted;
180 this.nonHeapMemoryUsed = nonHeapMemoryUsed;
181 this.nonHeapMemoryCommitted = nonHeapMemoryCommitted;
182 this.loadAverageLastMinute = loadAverageLastMinute;
183 this.freePhysicalMemory = freePhysicalMemory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100184 this.cpuUtilizationInJiffies = cpuUtilizationInJiffies;
185 }
186
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700187 /** Returns the time of the measurement in ms. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100188 public long getTimeInMs() {
189 return timeInNanos / 1000000;
190 }
191
192 /**
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700193 * Returns the amount of used heap memory in bytes at the time of measurement.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100194 *
195 * @see MemoryMXBean#getHeapMemoryUsage()
196 */
197 public long getHeapMemoryUsed() {
198 return heapMemoryUsed;
199 }
200
201 /**
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700202 * Returns the amount of used non heap memory in bytes at the time of measurement.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100203 *
204 * @see MemoryMXBean#getNonHeapMemoryUsage()
205 */
206 public long getHeapMemoryCommitted() {
207 return heapMemoryCommitted;
208 }
209
210 /**
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700211 * Returns the amount of memory in bytes that is committed for the Java virtual machine to use
212 * for the heap at the time of measurement.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100213 *
214 * @see MemoryMXBean#getHeapMemoryUsage()
215 */
216 public long getNonHeapMemoryUsed() {
217 return nonHeapMemoryUsed;
218 }
219
220 /**
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700221 * Returns the amount of memory in bytes that is committed for the Java virtual machine to use
222 * for non heap memory at the time of measurement.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100223 *
224 * @see MemoryMXBean#getNonHeapMemoryUsage()
225 */
226 public long getNonHeapMemoryCommitted() {
227 return nonHeapMemoryCommitted;
228 }
229
230 /**
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700231 * Returns the system load average for the last minute at the time of measurement.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100232 *
233 * @see OperatingSystemMXBean#getSystemLoadAverage()
234 */
235 public float getLoadAverageLastMinute() {
236 return loadAverageLastMinute;
237 }
238
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700239 /** Returns the free physical memmory in bytes at the time of measurement. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100240 public long getFreePhysicalMemory() {
241 return freePhysicalMemory;
242 }
243
244 /**
jhorvitz4fd8bbd2020-08-26 12:14:46 -0700245 * Returns the current cpu utilization of the current process in ms. The returned array contains
246 * the following information: The 1st entry is the number of ms that the process has executed in
247 * user mode, and the 2nd entry is the number of ms that the process has executed in kernel
248 * mode. Reads /proc/self/stat to obtain this information.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100249 */
250 public long[] getCpuUtilizationInMs() {
251 return new long[] {cpuUtilizationInJiffies[0] * 10, cpuUtilizationInJiffies[1] * 10};
252 }
253 }
254}