aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/util/ResourceUsage.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/util/ResourceUsage.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/util/ResourceUsage.java353
1 files changed, 353 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/util/ResourceUsage.java b/src/main/java/com/google/devtools/build/lib/util/ResourceUsage.java
new file mode 100644
index 0000000000..55807f2395
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/util/ResourceUsage.java
@@ -0,0 +1,353 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.util;
+
+import static java.nio.charset.StandardCharsets.US_ASCII;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+import com.google.common.io.Files;
+
+import com.sun.management.OperatingSystemMXBean;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.util.Iterator;
+
+/**
+ * Provides methods to measure the current resource usage of the current
+ * process. Also provides some convenience methods to obtain several system
+ * characteristics, like number of processors , total memory, etc.
+ */
+public final class ResourceUsage {
+
+ /*
+ * Use com.sun.management.OperatingSystemMXBean instead of
+ * java.lang.management.OperatingSystemMXBean because the latter does not
+ * support getTotalPhysicalMemorySize() and getFreePhysicalMemorySize().
+ */
+ private static final OperatingSystemMXBean OS_BEAN =
+ (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
+
+ private static final MemoryMXBean MEM_BEAN = ManagementFactory.getMemoryMXBean();
+ private static final Splitter WHITESPACE_SPLITTER = Splitter.on(CharMatcher.WHITESPACE);
+
+ /**
+ * Calculates an estimate of the current total CPU usage and the CPU usage of
+ * the process in percent measured from the two given measurements. The
+ * returned CPU usages rea average values for the time between the two
+ * measurements. The returned array contains the total CPU usage at index 0
+ * and the CPU usage of the measured process at index 1.
+ */
+ public static float[] calculateCurrentCpuUsage(Measurement oldMeasurement,
+ Measurement newMeasurement) {
+ if (oldMeasurement == null) {
+ return new float[2];
+ }
+ long idleJiffies =
+ newMeasurement.getTotalCpuIdleTimeInJiffies()
+ - oldMeasurement.getTotalCpuIdleTimeInJiffies();
+ long oldProcessJiffies =
+ oldMeasurement.getCpuUtilizationInJiffies()[0]
+ + oldMeasurement.getCpuUtilizationInJiffies()[1];
+ long newProcessJiffies =
+ newMeasurement.getCpuUtilizationInJiffies()[0]
+ + newMeasurement.getCpuUtilizationInJiffies()[1];
+ long processJiffies = newProcessJiffies - oldProcessJiffies;
+ long elapsedTimeJiffies =
+ newMeasurement.getTimeInJiffies() - oldMeasurement.getTimeInJiffies();
+ int processors = getAvailableProcessors();
+ // TODO(bazel-team): Sometimes smaller then zero. Not sure why.
+ double totalUsage = Math.max(0, 1.0D - (double) idleJiffies / elapsedTimeJiffies / processors);
+ double usage = Math.max(0, (double) processJiffies / elapsedTimeJiffies / processors);
+ return new float[] {(float) totalUsage * 100, (float) usage * 100};
+ }
+
+ private ResourceUsage() {
+ }
+
+ /**
+ * Returns the number of processors available to the Java virtual machine.
+ */
+ public static int getAvailableProcessors() {
+ return OS_BEAN.getAvailableProcessors();
+ }
+
+ /**
+ * Returns the total physical memory in bytes.
+ */
+ public static long getTotalPhysicalMemorySize() {
+ return OS_BEAN.getTotalPhysicalMemorySize();
+ }
+
+ /**
+ * Returns the operating system architecture.
+ */
+ public static String getOsArchitecture() {
+ return OS_BEAN.getArch();
+ }
+
+ /**
+ * Returns the operating system name.
+ */
+ public static String getOsName() {
+ return OS_BEAN.getName();
+ }
+
+ /**
+ * Returns the operating system version.
+ */
+ public static String getOsVersion() {
+ return OS_BEAN.getVersion();
+ }
+
+ /**
+ * Returns the initial size of heap memory in bytes.
+ *
+ * @see MemoryMXBean#getHeapMemoryUsage()
+ */
+ public static long getHeapMemoryInit() {
+ return MEM_BEAN.getHeapMemoryUsage().getInit();
+ }
+
+ /**
+ * Returns the initial size of non heap memory in bytes.
+ *
+ * @see MemoryMXBean#getNonHeapMemoryUsage()
+ */
+ public static long getNonHeapMemoryInit() {
+ return MEM_BEAN.getNonHeapMemoryUsage().getInit();
+ }
+
+ /**
+ * Returns the maximum size of heap memory in bytes.
+ *
+ * @see MemoryMXBean#getHeapMemoryUsage()
+ */
+ public static long getHeapMemoryMax() {
+ return MEM_BEAN.getHeapMemoryUsage().getMax();
+ }
+
+ /**
+ * Returns the maximum size of non heap memory in bytes.
+ *
+ * @see MemoryMXBean#getNonHeapMemoryUsage()
+ */
+ public static long getNonHeapMemoryMax() {
+ return MEM_BEAN.getNonHeapMemoryUsage().getMax();
+ }
+
+ /**
+ * Returns a measurement of the current resource usage of the current process.
+ */
+ public static Measurement measureCurrentResourceUsage() {
+ return measureCurrentResourceUsage("self");
+ }
+
+ /**
+ * Returns a measurement of the current resource usage of the process with the
+ * given process id.
+ *
+ * @param processId the process id or <code>self</code> for the current
+ * process.
+ */
+ public static Measurement measureCurrentResourceUsage(String processId) {
+ return new Measurement(MEM_BEAN.getHeapMemoryUsage().getUsed(), MEM_BEAN.getHeapMemoryUsage()
+ .getCommitted(), MEM_BEAN.getNonHeapMemoryUsage().getUsed(), MEM_BEAN
+ .getNonHeapMemoryUsage().getCommitted(), (float) OS_BEAN.getSystemLoadAverage(), OS_BEAN
+ .getFreePhysicalMemorySize(), getCurrentTotalIdleTimeInJiffies(),
+ getCurrentCpuUtilizationInJiffies(processId));
+ }
+
+ /**
+ * Returns the current total idle time of the processors since system boot.
+ * Reads /proc/stat to obtain this information.
+ */
+ private static long getCurrentTotalIdleTimeInJiffies() {
+ try {
+ File file = new File("/proc/stat");
+ String content = Files.toString(file, US_ASCII);
+ String value = Iterables.get(WHITESPACE_SPLITTER.split(content), 5);
+ return Long.parseLong(value);
+ } catch (NumberFormatException | IOException e) {
+ return 0L;
+ }
+ }
+
+ /**
+ * Returns the current cpu utilization of the current process with the given
+ * id in jiffies. The returned array contains the following information: The
+ * 1st entry is the number of jiffies that the process has executed in user
+ * mode, and the 2nd entry is the number of jiffies that the process has
+ * executed in kernel mode. Reads /proc/self/stat to obtain this information.
+ *
+ * @param processId the process id or <code>self</code> for the current
+ * process.
+ */
+ private static long[] getCurrentCpuUtilizationInJiffies(String processId) {
+ try {
+ File file = new File("/proc/" + processId + "/stat");
+ if (file.isDirectory()) {
+ return new long[2];
+ }
+ Iterator<String> stat = WHITESPACE_SPLITTER.split(
+ Files.toString(file, US_ASCII)).iterator();
+ for (int i = 0; i < 13; ++i) {
+ stat.next();
+ }
+ long token13 = Long.parseLong(stat.next());
+ long token14 = Long.parseLong(stat.next());
+ return new long[] { token13, token14 };
+ } catch (NumberFormatException e) {
+ return new long[2];
+ } catch (IOException e) {
+ return new long[2];
+ }
+ }
+
+ /**
+ * A snapshot of the resource usage of the current process at a point in time.
+ */
+ public static class Measurement {
+
+ private final long timeInNanos;
+ private final long heapMemoryUsed;
+ private final long heapMemoryCommitted;
+ private final long nonHeapMemoryUsed;
+ private final long nonHeapMemoryCommitted;
+ private final float loadAverageLastMinute;
+ private final long freePhysicalMemory;
+ private final long totalCpuIdleTimeInJiffies;
+ private final long[] cpuUtilizationInJiffies;
+
+ public Measurement(long heapMemoryUsed, long heapMemoryCommitted, long nonHeapMemoryUsed,
+ long nonHeapMemoryCommitted, float loadAverageLastMinute, long freePhysicalMemory,
+ long totalCpuIdleTimeInJiffies, long[] cpuUtilizationInJiffies) {
+ super();
+ timeInNanos = System.nanoTime();
+ this.heapMemoryUsed = heapMemoryUsed;
+ this.heapMemoryCommitted = heapMemoryCommitted;
+ this.nonHeapMemoryUsed = nonHeapMemoryUsed;
+ this.nonHeapMemoryCommitted = nonHeapMemoryCommitted;
+ this.loadAverageLastMinute = loadAverageLastMinute;
+ this.freePhysicalMemory = freePhysicalMemory;
+ this.totalCpuIdleTimeInJiffies = totalCpuIdleTimeInJiffies;
+ this.cpuUtilizationInJiffies = cpuUtilizationInJiffies;
+ }
+
+ /**
+ * Returns the time of the measurement in jiffies.
+ */
+ public long getTimeInJiffies() {
+ return timeInNanos / 10000000;
+ }
+
+ /**
+ * Returns the time of the measurement in ms.
+ */
+ public long getTimeInMs() {
+ return timeInNanos / 1000000;
+ }
+
+ /**
+ * Returns the amount of used heap memory in bytes at the time of
+ * measurement.
+ *
+ * @see MemoryMXBean#getHeapMemoryUsage()
+ */
+ public long getHeapMemoryUsed() {
+ return heapMemoryUsed;
+ }
+
+ /**
+ * Returns the amount of used non heap memory in bytes at the time of
+ * measurement.
+ *
+ * @see MemoryMXBean#getNonHeapMemoryUsage()
+ */
+ public long getHeapMemoryCommitted() {
+ return heapMemoryCommitted;
+ }
+
+ /**
+ * Returns the amount of memory in bytes that is committed for the Java
+ * virtual machine to use for the heap at the time of measurement.
+ *
+ * @see MemoryMXBean#getHeapMemoryUsage()
+ */
+ public long getNonHeapMemoryUsed() {
+ return nonHeapMemoryUsed;
+ }
+
+ /**
+ * Returns the amount of memory in bytes that is committed for the Java
+ * virtual machine to use for non heap memory at the time of measurement.
+ *
+ * @see MemoryMXBean#getNonHeapMemoryUsage()
+ */
+ public long getNonHeapMemoryCommitted() {
+ return nonHeapMemoryCommitted;
+ }
+
+ /**
+ * Returns the system load average for the last minute at the time of
+ * measurement.
+ *
+ * @see OperatingSystemMXBean#getSystemLoadAverage()
+ */
+ public float getLoadAverageLastMinute() {
+ return loadAverageLastMinute;
+ }
+
+ /**
+ * Returns the free physical memmory in bytes at the time of measurement.
+ */
+ public long getFreePhysicalMemory() {
+ return freePhysicalMemory;
+ }
+
+ /**
+ * Returns the current total cpu idle since system boot in jiffies.
+ */
+ public long getTotalCpuIdleTimeInJiffies() {
+ return totalCpuIdleTimeInJiffies;
+ }
+
+ /**
+ * Returns the current cpu utilization of the current process in jiffies.
+ * The returned array contains the following information: The 1st entry is
+ * the number of jiffies that the process has executed in user mode, and the
+ * 2nd entry is the number of jiffies that the process has executed in
+ * kernel mode. Reads /proc/self/stat to obtain this information.
+ */
+ public long[] getCpuUtilizationInJiffies() {
+ return cpuUtilizationInJiffies;
+ }
+
+ /**
+ * Returns the current cpu utilization of the current process in ms. The
+ * returned array contains the following information: The 1st entry is the
+ * number of ms that the process has executed in user mode, and the 2nd
+ * entry is the number of ms that the process has executed in kernel mode.
+ * Reads /proc/self/stat to obtain this information.
+ */
+ public long[] getCpuUtilizationInMs() {
+ return new long[] {cpuUtilizationInJiffies[0] * 10, cpuUtilizationInJiffies[1] * 10};
+ }
+ }
+}