// Copyright 2014 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.chart; import com.google.devtools.build.lib.profiler.ProfileInfo; import com.google.devtools.build.lib.profiler.ProfileInfo.Task; import com.google.devtools.build.lib.profiler.ProfilerTask; import java.util.EnumSet; import java.util.Set; /** * Implementation of {@link ChartCreator} that creates Gantt Charts that try to * minimize the number of bars while preserving as much information about the * execution of actions as possible. * * <p>Profiler tasks are categorized into four categories: * <ul> * <li>Actions: Actions executed. * <li>Blaze Internal: This category contains internal blaze tasks, like loading * packages, saving the action cache etc. * <li>Locks: Contains tasks that indicate that a thread is waiting for * resources. * <li>VFS: Contains tasks that access the file system. * </ul> */ public class AggregatingChartCreator implements ChartCreator { /** The tasks in the 'actions' category. */ private static final Set<ProfilerTask> ACTION_TASKS = EnumSet.of(ProfilerTask.ACTION, ProfilerTask.ACTION_SUBMIT); /** The tasks in the 'blaze internal' category. */ private static Set<ProfilerTask> BLAZE_TASKS = EnumSet.of(ProfilerTask.CREATE_PACKAGE, ProfilerTask.PACKAGE_VALIDITY_CHECK, ProfilerTask.CONFIGURED_TARGET, ProfilerTask.TRANSITIVE_CLOSURE, ProfilerTask.EXCEPTION, ProfilerTask.INFO, ProfilerTask.UNKNOWN); /** The tasks in the 'locks' category. */ private static Set<ProfilerTask> LOCK_TASKS = EnumSet.of(ProfilerTask.ACTION_LOCK, ProfilerTask.WAIT); /** The tasks in the 'VFS' category. */ private static Set<ProfilerTask> VFS_TASKS = EnumSet.of(ProfilerTask.VFS_STAT, ProfilerTask.VFS_DIR, ProfilerTask.VFS_READLINK, ProfilerTask.VFS_MD5, ProfilerTask.VFS_DELETE, ProfilerTask.VFS_OPEN, ProfilerTask.VFS_READ, ProfilerTask.VFS_WRITE, ProfilerTask.VFS_GLOB, ProfilerTask.VFS_XATTR); /** The data of the profiled build. */ private final ProfileInfo info; /** If true, VFS related information is added to the chart. */ private final boolean showVFS; /** The type for bars of category 'blaze internal'. */ private ChartBarType blazeType; /** The type for bars of category 'actions'. */ private ChartBarType actionType; /** The type for bars of category 'locks'. */ private ChartBarType lockType; /** The type for bars of category 'VFS'. */ private ChartBarType vfsType; /** * Creates the chart creator. The created {@link ChartCreator} does not add * VFS related data to the generated chart. * * @param info the data of the profiled build */ public AggregatingChartCreator(ProfileInfo info) { this(info, false); } /** * Creates the chart creator. * * @param info the data of the profiled build * @param showVFS if true, VFS related information is added to the chart */ public AggregatingChartCreator(ProfileInfo info, boolean showVFS) { this.info = info; this.showVFS = showVFS; } @Override public Chart create() { Chart chart = new Chart(); CommonChartCreator.createCommonChartItems(chart, info); createTypes(chart); for (ProfileInfo.Task task : info.allTasksById) { if (ACTION_TASKS.contains(task.type)) { createBar(chart, task, actionType); } else if (LOCK_TASKS.contains(task.type)) { createBar(chart, task, lockType); } else if (BLAZE_TASKS.contains(task.type)) { createBar(chart, task, blazeType); } else if (showVFS && VFS_TASKS.contains(task.type)) { createBar(chart, task, vfsType); } } return chart; } /** * Creates a bar and adds it to the chart. * * @param chart the chart to add the types to * @param task the profiler task from which the bar is created * @param type the type of the bar */ private void createBar(Chart chart, Task task, ChartBarType type) { String label = task.type.description + ": " + task.getDescription(); chart.addBar(task.threadId, task.startTime, task.startTime + task.durationNanos, type, label); } /** * Creates the {@link ChartBarType}s and adds them to the chart. * * @param chart the chart to add the types to */ private void createTypes(Chart chart) { actionType = chart.createType("Action processing", new Color(0x000099)); blazeType = chart.createType("Blaze internal processing", new Color(0x999999)); lockType = chart.createType("Waiting for resources", new Color(0x990000)); if (showVFS) { vfsType = chart.createType("File system access", new Color(0x009900)); } } }