aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/profiler/chart/AggregatingChartCreator.java
blob: 85b28a6bcb9a1ed3cedd1d5a152fa36a824c6213 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// 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.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.duration, 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));
    }
  }
}