blob: ff98837f8dfd7917bbeab69ce0af1177928fecf5 [file] [log] [blame]
// Copyright 2015 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.profiler.statistics;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.devtools.build.lib.profiler.analysis.ProfileInfo;
import com.google.devtools.build.lib.profiler.analysis.ProfileInfo.Task;
import com.google.devtools.build.lib.util.LongArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* Extracts the execution times of user-defined and built-in Skylark functions and computes
* statistics.
*
* <p>The statistics are separated for the total duration taken for a function call and the
* "self duration" taken only within the function itself, but not within any subtask of the
* corresponding {@link Task}.
*/
public final class SkylarkStatistics {
private final Map<String, LongArrayList> userFunctionDurations;
private final Map<String, LongArrayList> userCompiledDurations;
private final Map<String, LongArrayList> builtinFunctionDurations;
/**
* Self duration is the time taken just within a function itself, but not other subtasks of it.
*/
private final Map<String, LongArrayList> userFunctionSelfDurations;
private final Map<String, LongArrayList> userCompiledSelfDurations;
private final Map<String, LongArrayList> builtinFunctionSelfDurations;
private long userTotalNanos;
private long userCompiledTotalNanos;
private long builtinTotalNanos;
public SkylarkStatistics() {
userFunctionDurations = new HashMap<>();
userCompiledDurations = new HashMap<>();
builtinFunctionDurations = new HashMap<>();
userFunctionSelfDurations = new HashMap<>();
userCompiledSelfDurations = new HashMap<>();
builtinFunctionSelfDurations = new HashMap<>();
}
public SkylarkStatistics(ProfileInfo info) {
this();
addProfileInfo(info);
}
/**
* Adds Skylark function task durations from a {@link ProfileInfo} file.
*/
public void addProfileInfo(ProfileInfo info) {
computeStatistics(
info.getSkylarkUserFunctionTasks(),
info.getCompiledSkylarkUserFunctionTasks(),
info.getSkylarkBuiltinFunctionTasks());
}
/**
* @return the total time taken by all calls to built-in Skylark functions
*/
public long getBuiltinTotalNanos() {
return builtinTotalNanos;
}
/**
* @return the total time taken by all calls to user-defined Skylark functions
*/
public long getCompiledUserTotalNanos() {
return userCompiledTotalNanos;
}
/**
* @return the total time taken by all calls to user-defined Skylark functions
*/
public long getUserTotalNanos() {
return userTotalNanos;
}
/**
* @return The execution durations of all calls to built-in Skylark functions.
*/
public Map<String, LongArrayList> getBuiltinFunctionDurations() {
return builtinFunctionDurations;
}
/**
* return The execution durations of all calls to built-in functions excluding the durations of
* all subtasks.
*/
public Map<String, LongArrayList> getBuiltinFunctionSelfDurations() {
return builtinFunctionSelfDurations;
}
/**
* Builds and returns the {@link TasksStatistics} for the durations of each built-in function.
* The return value is not cached and will be recomputed on another call.
*/
public Map<String, TasksStatistics> getBuiltinFunctionStatistics() {
return buildTasksStatistics(builtinFunctionDurations);
}
/**
* Builds and returns the {@link TasksStatistics} for the self-times of each built-in function.
* The return value is not cached and will be recomputed on another call.
*/
public Map<String, TasksStatistics> getBuiltinFunctionSelfStatistics() {
return buildTasksStatistics(builtinFunctionSelfDurations);
}
/**
* @return The execution durations of all calls to user-defined Skylark functions.
*/
public Map<String, LongArrayList> getCompiledUserFunctionDurations() {
return userCompiledDurations;
}
/**
* return The execution durations of all calls to user-defined functions excluding the durations
* of all subtasks.
*/
public Map<String, LongArrayList> getCompiledUserFunctionSelfDurations() {
return userCompiledSelfDurations;
}
/**
* Builds and returns the {@link TasksStatistics} for the durations of each user-defined
* function. The return value is not cached and will be recomputed on another call.
*/
public Map<String, TasksStatistics> getCompiledUserFunctionStatistics() {
return buildTasksStatistics(userCompiledDurations);
}
/**
* Builds and returns the {@link TasksStatistics} for the self-times of each user-defined
* function. The return value is not cached and will be recomputed on another call.
*/
public Map<String, TasksStatistics> getCompiledUserFunctionSelfStatistics() {
return buildTasksStatistics(userCompiledSelfDurations);
}
/**
* @return The execution durations of all calls to user-defined Skylark functions.
*/
public Map<String, LongArrayList> getUserFunctionDurations() {
return userFunctionDurations;
}
/**
* return The execution durations of all calls to user-defined functions excluding the durations
* of all subtasks.
*/
public Map<String, LongArrayList> getUserFunctionSelfDurations() {
return userFunctionSelfDurations;
}
/**
* Builds and returns the {@link TasksStatistics} for the durations of each user-defined
* function. The return value is not cached and will be recomputed on another call.
*/
public Map<String, TasksStatistics> getUserFunctionStatistics() {
return buildTasksStatistics(userFunctionDurations);
}
/**
* Builds and returns the {@link TasksStatistics} for the self-times of each user-defined
* function. The return value is not cached and will be recomputed on another call.
*/
public Map<String, TasksStatistics> getUserFunctionSelfStatistics() {
return buildTasksStatistics(userFunctionSelfDurations);
}
/**
* For each Skylark function get the list of durations and self durations from the task maps.
*/
private void computeStatistics(
Multimap<String, Task> userTasks,
Multimap<String, Task> userCompiledTasks,
Multimap<String, Task> builtinTasks) {
userTotalNanos += addDurations(userTasks, userFunctionDurations, userFunctionSelfDurations);
userCompiledTotalNanos +=
addDurations(userCompiledTasks, userCompiledDurations, userCompiledSelfDurations);
builtinTotalNanos +=
addDurations(builtinTasks, builtinFunctionDurations, builtinFunctionSelfDurations);
}
/**
* Add all new durations to previously collected durations for all functions mapped to tasks.
* @return The sum of the execution times of all {@link Task} values in the map.
*/
private static long addDurations(
Multimap<String, Task> functionTasks,
Map<String, LongArrayList> durationsMap,
Map<String, LongArrayList> selfDurationsMap) {
long totalTime = 0;
for (Map.Entry<String, Collection<Task>> entry : functionTasks.asMap().entrySet()) {
String function = entry.getKey();
Collection<Task> tasks = entry.getValue();
LongArrayList durations;
LongArrayList selfDurations;
if (durationsMap.containsKey(function)) {
durations = durationsMap.get(function);
selfDurations = selfDurationsMap.get(function);
} else {
durations = new LongArrayList(tasks.size());
selfDurations = new LongArrayList(tasks.size());
durationsMap.put(function, durations);
selfDurationsMap.put(function, selfDurations);
}
totalTime += addDurations(tasks, durations, selfDurations);
}
return totalTime;
}
/**
* Add all durations and self-times of the given function to the maps.
* @return The sum of the execution times of all {@link Task} values in the collection.
*/
private static long addDurations(
Collection<Task> tasks, LongArrayList durations, LongArrayList selfDurations) {
long totalTime = 0;
durations.ensureCapacity(durations.size() + tasks.size());
selfDurations.ensureCapacity(selfDurations.size() + tasks.size());
for (Task task : tasks) {
durations.add(task.durationNanos);
selfDurations.add(task.durationNanos - task.getInheritedDuration());
totalTime += task.durationNanos;
}
return totalTime;
}
/**
* Build a Map of {@link TasksStatistics} from the given duration maps.
*/
private static Map<String, TasksStatistics> buildTasksStatistics(
final Map<String, LongArrayList> durationsMap) {
return Maps.transformEntries(durationsMap, TasksStatistics::create);
}
}