Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2014 The Bazel Authors. All rights reserved. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 2 | // |
| 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 | |
| 15 | package com.google.devtools.build.lib.util; |
| 16 | |
| 17 | import static java.nio.charset.StandardCharsets.US_ASCII; |
| 18 | |
| 19 | import com.google.common.base.CharMatcher; |
| 20 | import com.google.common.base.Splitter; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 21 | import com.google.common.io.Files; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 22 | import com.sun.management.OperatingSystemMXBean; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 23 | import java.io.File; |
| 24 | import java.io.IOException; |
| 25 | import java.lang.management.ManagementFactory; |
| 26 | import java.lang.management.MemoryMXBean; |
jhorvitz | 49cb5a6 | 2020-09-17 08:48:39 -0700 | [diff] [blame] | 27 | import java.util.List; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 28 | |
| 29 | /** |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 30 | * 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 Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 33 | */ |
| 34 | public 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(); |
Googler | e92bfe5 | 2016-03-07 19:32:24 +0000 | [diff] [blame] | 45 | private static final Splitter WHITESPACE_SPLITTER = Splitter.on(CharMatcher.whitespace()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 46 | |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 47 | private ResourceUsage() {} |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 48 | |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 49 | /** Returns the number of processors available to the Java virtual machine. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 50 | public static int getAvailableProcessors() { |
| 51 | return OS_BEAN.getAvailableProcessors(); |
| 52 | } |
| 53 | |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 54 | /** Returns the total physical memory in bytes. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 55 | public static long getTotalPhysicalMemorySize() { |
| 56 | return OS_BEAN.getTotalPhysicalMemorySize(); |
| 57 | } |
| 58 | |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 59 | /** Returns the operating system architecture. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 60 | public static String getOsArchitecture() { |
| 61 | return OS_BEAN.getArch(); |
| 62 | } |
| 63 | |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 64 | /** Returns the operating system name. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 65 | public static String getOsName() { |
| 66 | return OS_BEAN.getName(); |
| 67 | } |
| 68 | |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 69 | /** Returns the operating system version. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 70 | 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 | |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 110 | /** Returns a measurement of the current resource usage of the current process. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 111 | public static Measurement measureCurrentResourceUsage() { |
| 112 | return measureCurrentResourceUsage("self"); |
| 113 | } |
| 114 | |
| 115 | /** |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 116 | * Returns a measurement of the current resource usage of the process with the given process id. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 117 | * |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 118 | * @param processId the process id or <code>self</code> for the current process. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 119 | */ |
| 120 | public static Measurement measureCurrentResourceUsage(String processId) { |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 121 | 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 Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 128 | getCurrentCpuUtilizationInJiffies(processId)); |
| 129 | } |
| 130 | |
| 131 | /** |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 132 | * 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 Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 136 | * |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 137 | * @param processId the process id or <code>self</code> for the current process. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 138 | */ |
| 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 | } |
jhorvitz | 49cb5a6 | 2020-09-17 08:48:39 -0700 | [diff] [blame] | 145 | 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 Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 149 | } |
jhorvitz | 49cb5a6 | 2020-09-17 08:48:39 -0700 | [diff] [blame] | 150 | return new long[] {Long.parseLong(stat.get(13)), Long.parseLong(stat.get(14))}; |
Ulf Adams | 07dba94 | 2015-03-05 14:47:37 +0000 | [diff] [blame] | 151 | } catch (NumberFormatException | IOException e) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 152 | return new long[2]; |
| 153 | } |
| 154 | } |
| 155 | |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 156 | /** A snapshot of the resource usage of the current process at a point in time. */ |
| 157 | public static final class Measurement { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 158 | |
| 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 Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 166 | private final long[] cpuUtilizationInJiffies; |
| 167 | |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 168 | 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 Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 176 | 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 Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 184 | this.cpuUtilizationInJiffies = cpuUtilizationInJiffies; |
| 185 | } |
| 186 | |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 187 | /** Returns the time of the measurement in ms. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 188 | public long getTimeInMs() { |
| 189 | return timeInNanos / 1000000; |
| 190 | } |
| 191 | |
| 192 | /** |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 193 | * Returns the amount of used heap memory in bytes at the time of measurement. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 194 | * |
| 195 | * @see MemoryMXBean#getHeapMemoryUsage() |
| 196 | */ |
| 197 | public long getHeapMemoryUsed() { |
| 198 | return heapMemoryUsed; |
| 199 | } |
| 200 | |
| 201 | /** |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 202 | * Returns the amount of used non heap memory in bytes at the time of measurement. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 203 | * |
| 204 | * @see MemoryMXBean#getNonHeapMemoryUsage() |
| 205 | */ |
| 206 | public long getHeapMemoryCommitted() { |
| 207 | return heapMemoryCommitted; |
| 208 | } |
| 209 | |
| 210 | /** |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 211 | * 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 Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 213 | * |
| 214 | * @see MemoryMXBean#getHeapMemoryUsage() |
| 215 | */ |
| 216 | public long getNonHeapMemoryUsed() { |
| 217 | return nonHeapMemoryUsed; |
| 218 | } |
| 219 | |
| 220 | /** |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 221 | * 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 Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 223 | * |
| 224 | * @see MemoryMXBean#getNonHeapMemoryUsage() |
| 225 | */ |
| 226 | public long getNonHeapMemoryCommitted() { |
| 227 | return nonHeapMemoryCommitted; |
| 228 | } |
| 229 | |
| 230 | /** |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 231 | * Returns the system load average for the last minute at the time of measurement. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 232 | * |
| 233 | * @see OperatingSystemMXBean#getSystemLoadAverage() |
| 234 | */ |
| 235 | public float getLoadAverageLastMinute() { |
| 236 | return loadAverageLastMinute; |
| 237 | } |
| 238 | |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 239 | /** Returns the free physical memmory in bytes at the time of measurement. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 240 | public long getFreePhysicalMemory() { |
| 241 | return freePhysicalMemory; |
| 242 | } |
| 243 | |
| 244 | /** |
jhorvitz | 4fd8bbd | 2020-08-26 12:14:46 -0700 | [diff] [blame] | 245 | * 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 Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 249 | */ |
| 250 | public long[] getCpuUtilizationInMs() { |
| 251 | return new long[] {cpuUtilizationInJiffies[0] * 10, cpuUtilizationInJiffies[1] * 10}; |
| 252 | } |
| 253 | } |
| 254 | } |