// Copyright 2017 The Bazel Authors. 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.shell; import com.google.devtools.build.lib.vfs.Path; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.time.Duration; import java.util.Optional; /** Provides execution statistics (e.g. resource usage) for external commands. */ public final class ExecutionStatistics { /** * Provides execution statistics based on a {@code execution_statistics.proto} file. * * @param executionStatisticsProtoPath path to a materialized ExecutionStatistics proto * @return a {@link ResourceUsage} object containing execution statistics, if available */ public static Optional getResourceUsage(Path executionStatisticsProtoPath) throws IOException { try (InputStream protoInputStream = new BufferedInputStream(executionStatisticsProtoPath.getInputStream())) { Protos.ExecutionStatistics executionStatisticsProto = Protos.ExecutionStatistics.parseFrom(protoInputStream); if (executionStatisticsProto.hasResourceUsage()) { return Optional.of(new ResourceUsage(executionStatisticsProto.getResourceUsage())); } else { return Optional.empty(); } } } /** * Provides resource usage statistics for command execution, derived from the getrusage() system * call. */ public static class ResourceUsage { private final Protos.ResourceUsage resourceUsageProto; /** Provides resource usage statistics via a ResourceUsage proto object. */ public ResourceUsage(Protos.ResourceUsage resourceUsageProto) { this.resourceUsageProto = resourceUsageProto; } /** Returns the user time for command execution, if available. */ public Duration getUserExecutionTime() { return Duration.ofSeconds( resourceUsageProto.getUtimeSec(), resourceUsageProto.getUtimeUsec() * 1000); } /** Returns the system time for command execution, if available. */ public Duration getSystemExecutionTime() { return Duration.ofSeconds( resourceUsageProto.getStimeSec(), resourceUsageProto.getStimeUsec() * 1000); } /** Returns the maximum resident set size (in bytes) during command execution, if available. */ public long getMaximumResidentSetSize() { return resourceUsageProto.getMaxrss(); } /** * Returns the integral shared memory size (in bytes) during command execution, if available. */ public long getIntegralSharedMemorySize() { return resourceUsageProto.getIxrss(); } /** * Returns the integral unshared data size (in bytes) during command execution, if available. */ public long getIntegralUnsharedDataSize() { return resourceUsageProto.getIdrss(); } /** * Returns the integral unshared stack size (in bytes) during command execution, if available. */ public long getIntegralUnsharedStackSize() { return resourceUsageProto.getIsrss(); } /** * Returns the number of page reclaims (soft page faults) during command execution, if * available. */ public long getPageReclaims() { return resourceUsageProto.getMinflt(); } /** Returns the number of (hard) page faults during command execution, if available. */ public long getPageFaults() { return resourceUsageProto.getMajflt(); } /** Returns the number of swaps during command execution, if available. */ public long getSwaps() { return resourceUsageProto.getNswap(); } /** Returns the number of block input operations during command execution, if available. */ public long getBlockInputOperations() { return resourceUsageProto.getInblock(); } /** Returns the number of block output operations during command execution, if available. */ public long getBlockOutputOperations() { return resourceUsageProto.getOublock(); } /** Returns the number of IPC messages sent during command execution, if available. */ public long getIpcMessagesSent() { return resourceUsageProto.getMsgsnd(); } /** Returns the number of IPC messages received during command execution, if available. */ public long getIpcMessagesReceived() { return resourceUsageProto.getMsgrcv(); } /** Returns the number of signals received during command execution, if available. */ public long getSignalsReceived() { return resourceUsageProto.getNsignals(); } /** Returns the number of voluntary context switches during command execution, if available. */ public long getVoluntaryContextSwitches() { return resourceUsageProto.getNvcsw(); } /** * Returns the number of involuntary context switches during command execution, if available. */ public long getInvoluntaryContextSwitches() { return resourceUsageProto.getNivcsw(); } } }