blob: 7292378a2a870e66efb9e87f1b5949ea984c025b [file] [log] [blame]
Florian Weikert2be2f382015-12-07 15:02:00 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.profiler;
15
16import static com.google.common.truth.Truth.assertThat;
Florian Weikert2be2f382015-12-07 15:02:00 +000017
18import com.google.devtools.build.lib.profiler.Profiler.ProfiledTaskKinds;
19import com.google.devtools.build.lib.profiler.chart.AggregatingChartCreator;
20import com.google.devtools.build.lib.profiler.chart.Chart;
21import com.google.devtools.build.lib.profiler.chart.ChartBar;
22import com.google.devtools.build.lib.profiler.chart.ChartBarType;
23import com.google.devtools.build.lib.profiler.chart.ChartColumn;
24import com.google.devtools.build.lib.profiler.chart.ChartCreator;
25import com.google.devtools.build.lib.profiler.chart.ChartLine;
26import com.google.devtools.build.lib.profiler.chart.ChartRow;
27import com.google.devtools.build.lib.profiler.chart.ChartVisitor;
28import com.google.devtools.build.lib.profiler.chart.Color;
29import com.google.devtools.build.lib.profiler.chart.DetailedChartCreator;
30import com.google.devtools.build.lib.testutil.FoundationTestCase;
31import com.google.devtools.build.lib.testutil.Scratch;
32import com.google.devtools.build.lib.testutil.Suite;
33import com.google.devtools.build.lib.testutil.TestSpec;
34import com.google.devtools.build.lib.util.BlazeClock;
35import com.google.devtools.build.lib.vfs.Path;
lberkibf6ef0f2017-05-29 11:00:40 +020036import java.util.List;
Florian Weikert2be2f382015-12-07 15:02:00 +000037import org.junit.Test;
38import org.junit.runner.RunWith;
39import org.junit.runners.JUnit4;
40
lberkibf6ef0f2017-05-29 11:00:40 +020041/** Unit tests for the profiler chart generation. */
Florian Weikert2be2f382015-12-07 15:02:00 +000042@TestSpec(size = Suite.MEDIUM_TESTS)
43@RunWith(JUnit4.class)
44public class ProfilerChartTest extends FoundationTestCase {
45 private static final int COMMON_CHART_TYPES = ProfilePhase.values().length;
46 private static final int DETAILED_CHART_TYPES = ProfilerTask.values().length;
47 private static final int AGGREGATED_CHART_TYPES = 4;
48 private static final int AGGREGATED_CHART_NO_VFS_TYPES = 3;
49
50 @Test
51 public void testChartCreators() throws Exception {
52 Runnable run = new Runnable() {
53 @Override
54 public void run() {
55 Profiler.instance().startTask(ProfilerTask.ACTION, "action");
56 Profiler.instance().completeTask(ProfilerTask.ACTION);
57 }
58 };
59 int threads = 4; // there is one extra thread due due the event that finalizes the profiler
60 ProfileInfo info = createProfileInfo(run, threads - 1);
61 ChartCreator aggregatingCreator = new AggregatingChartCreator(info, true);
62 Chart aggregatedChart = aggregatingCreator.create();
lberkibf6ef0f2017-05-29 11:00:40 +020063 assertThat(aggregatedChart.getRowCount()).isEqualTo(threads);
Florian Weikert2be2f382015-12-07 15:02:00 +000064 assertThat(aggregatedChart.getSortedRows().get(0).getBars()).hasSize(1);
65
66 ChartCreator detailedCreator = new DetailedChartCreator(info);
67 Chart detailedChart = detailedCreator.create();
68 assertThat(detailedChart.getSortedTypes()).hasSize(COMMON_CHART_TYPES + DETAILED_CHART_TYPES);
lberkibf6ef0f2017-05-29 11:00:40 +020069 assertThat(detailedChart.getRowCount()).isEqualTo(threads);
Florian Weikert2be2f382015-12-07 15:02:00 +000070 assertThat(detailedChart.getSortedRows().get(0).getBars()).hasSize(1);
71 }
72
73 @Test
74 public void testAggregatingChartCreator() throws Exception {
75 Runnable run = new Runnable() {
76 @Override
77 public void run() {
78 Profiler profiler = Profiler.instance();
79 profiler.startTask(ProfilerTask.ACTION, "action"); // Stays
80 task(profiler, ProfilerTask.REMOTE_EXECUTION, "remote execution"); // Removed
81 task(profiler, ProfilerTask.ACTION_CHECK, "check"); // Removed
82 task(profiler, ProfilerTask.ACTION_LOCK, "lock"); // Stays
83 profiler.completeTask(ProfilerTask.ACTION);
84 task(profiler, ProfilerTask.INFO, "info"); // Stays
85 task(profiler, ProfilerTask.VFS_STAT, "stat"); // Stays, if showVFS
86 task(profiler, ProfilerTask.WAIT, "wait"); // Stays
87 }
88 };
89 ProfileInfo info = createProfileInfo(run, 1);
90
91 ChartCreator aggregatingCreator = new AggregatingChartCreator(info, true);
92 Chart aggregatedChart = aggregatingCreator.create();
93 assertThat(aggregatedChart.getSortedTypes())
94 .hasSize(COMMON_CHART_TYPES + AGGREGATED_CHART_TYPES);
95 assertThat(aggregatedChart.getSortedRows().get(0).getBars()).hasSize(5);
96
97 ChartCreator aggregatingNoVfsCreator = new AggregatingChartCreator(info, false);
98 Chart aggregatedNoVfsChart = aggregatingNoVfsCreator.create();
99 assertThat(aggregatedNoVfsChart.getSortedTypes())
100 .hasSize(COMMON_CHART_TYPES + AGGREGATED_CHART_NO_VFS_TYPES);
101 assertThat(aggregatedNoVfsChart.getSortedRows().get(0).getBars()).hasSize(4);
102
103 ChartCreator detailedCreator = new DetailedChartCreator(info);
104 Chart detailedChart = detailedCreator.create();
105 assertThat(detailedChart.getSortedTypes())
106 .hasSize(COMMON_CHART_TYPES + ProfilerTask.values().length);
107 assertThat(detailedChart.getSortedRows().get(0).getBars()).hasSize(7);
108 }
109
110 @Test
111 public void testChart() throws Exception {
112 Chart chart = new Chart();
113
114 ChartBarType type3 = chart.createType("name3", Color.GREEN);
115 ChartBarType type2 = chart.createType("name2", Color.RED);
116 ChartBarType type1 = chart.createType("name1", Color.BLACK);
117 List<ChartBarType> types = chart.getSortedTypes();
118 assertThat(types).hasSize(3);
lberkibf6ef0f2017-05-29 11:00:40 +0200119 assertThat(types.get(0).getName()).isEqualTo(type1.getName());
120 assertThat(types.get(0).getColor()).isEqualTo(type1.getColor());
121 assertThat(types.get(1).getName()).isEqualTo(type2.getName());
122 assertThat(types.get(1).getColor()).isEqualTo(type2.getColor());
123 assertThat(types.get(2).getName()).isEqualTo(type3.getName());
124 assertThat(types.get(2).getColor()).isEqualTo(type3.getColor());
Florian Weikert2be2f382015-12-07 15:02:00 +0000125
lberkibf6ef0f2017-05-29 11:00:40 +0200126 assertThat(chart.lookUpType("name3")).isSameAs(type3);
127 assertThat(chart.lookUpType("name2")).isSameAs(type2);
128 assertThat(chart.lookUpType("name1")).isSameAs(type1);
Florian Weikert2be2f382015-12-07 15:02:00 +0000129
lberkibf6ef0f2017-05-29 11:00:40 +0200130 assertThat(chart.lookUpType("wergl")).isSameAs(Chart.UNKNOWN_TYPE);
Florian Weikert2be2f382015-12-07 15:02:00 +0000131 types = chart.getSortedTypes();
132 assertThat(types).hasSize(4);
133
134 chart.addBar(1, 2, 3, type1, "label1");
135 chart.addBar(2, 3, 4, type2, "label2");
136 chart.addBar(2, 4, 5, type3, "label3");
137 chart.addBar(3, 3, 4, type2, "label4");
138 chart.addBar(3, 4, 5, type3, "label5");
139 chart.addBar(3, 5, 6, type3, "label6");
140
lberkibf6ef0f2017-05-29 11:00:40 +0200141 assertThat(chart.getMaxStop()).isEqualTo(6);
142 assertThat(chart.getRowCount()).isEqualTo(3);
Florian Weikert2be2f382015-12-07 15:02:00 +0000143
144 List<ChartRow> rows = chart.getSortedRows();
145 assertThat(rows).hasSize(3);
146 assertThat(rows.get(0).getBars()).hasSize(1);
147 assertThat(rows.get(1).getBars()).hasSize(2);
148 assertThat(rows.get(2).getBars()).hasSize(3);
149
150 ChartBar bar = rows.get(0).getBars().get(0);
lberkibf6ef0f2017-05-29 11:00:40 +0200151 assertThat(bar.getStart()).isEqualTo(2);
152 assertThat(bar.getStop()).isEqualTo(3);
153 assertThat(bar.getType()).isSameAs(type1);
154 assertThat(bar.getLabel()).isEqualTo("label1");
Florian Weikert2be2f382015-12-07 15:02:00 +0000155 }
156
157 @Test
158 public void testChartRows() throws Exception {
159 ChartRow row1 = new ChartRow("1", 0);
160 ChartRow row2 = new ChartRow("2", 1);
161 ChartRow row3 = new ChartRow("3", 1);
162
lberkibf6ef0f2017-05-29 11:00:40 +0200163 assertThat(row1.getId()).isEqualTo("1");
164 assertThat(row1.getIndex()).isEqualTo(0);
Florian Weikert2be2f382015-12-07 15:02:00 +0000165
lberkibf6ef0f2017-05-29 11:00:40 +0200166 assertThat(row1.compareTo(row2)).isEqualTo(-1);
167 assertThat(row2.compareTo(row1)).isEqualTo(1);
168 assertThat(row2.compareTo(row3)).isEqualTo(0);
Florian Weikert2be2f382015-12-07 15:02:00 +0000169
170 row1.addBar(new ChartBar(row1, 1, 2, new ChartBarType("name1", Color.BLACK), false, "label1"));
171 row1.addBar(new ChartBar(row1, 2, 3, new ChartBarType("name2", Color.RED), false, "label2"));
172
173 assertThat(row1.getBars()).hasSize(2);
lberkibf6ef0f2017-05-29 11:00:40 +0200174 assertThat(row1.getBars().get(0).getLabel()).isEqualTo("label1");
175 assertThat(row1.getBars().get(1).getLabel()).isEqualTo("label2");
Florian Weikert2be2f382015-12-07 15:02:00 +0000176 }
177
178 @Test
179 public void testChartBarTypes() throws Exception {
180 ChartBarType type1 = new ChartBarType("name1", Color.BLACK);
181 ChartBarType type2 = new ChartBarType("name2", Color.RED);
182 ChartBarType type3 = new ChartBarType("name2", Color.GREEN);
183
lberkibf6ef0f2017-05-29 11:00:40 +0200184 assertThat(type1.compareTo(type2)).isEqualTo(-1);
185 assertThat(type2.compareTo(type1)).isEqualTo(1);
186 assertThat(type2.compareTo(type3)).isEqualTo(0);
Florian Weikert2be2f382015-12-07 15:02:00 +0000187
lberkibf6ef0f2017-05-29 11:00:40 +0200188 assertThat(type2).isEqualTo(type3);
189 assertThat(type1.equals(type3)).isFalse();
190 assertThat(type1.equals(type2)).isFalse();
Florian Weikert2be2f382015-12-07 15:02:00 +0000191
lberkibf6ef0f2017-05-29 11:00:40 +0200192 assertThat(type2.hashCode()).isEqualTo(type3.hashCode());
193 assertThat(type1.hashCode() == type2.hashCode()).isFalse();
194 assertThat(type1.hashCode() == type3.hashCode()).isFalse();
Florian Weikert2be2f382015-12-07 15:02:00 +0000195 }
196
197 @Test
198 public void testChartBar() throws Exception {
199 ChartRow row1 = new ChartRow("1", 0);
200 ChartBarType type = new ChartBarType("name1", Color.BLACK);
201 ChartBar bar1 = new ChartBar(row1, 1, 2, type, false, "label1");
lberkibf6ef0f2017-05-29 11:00:40 +0200202 assertThat(bar1.getRow()).isEqualTo(row1);
203 assertThat(bar1.getStart()).isEqualTo(1);
204 assertThat(bar1.getStop()).isEqualTo(2);
205 assertThat(bar1.getType()).isSameAs(type);
206 assertThat(bar1.getLabel()).isEqualTo("label1");
Florian Weikert2be2f382015-12-07 15:02:00 +0000207 }
208
209 @Test
210 public void testVisitor() throws Exception {
211 Chart chart = new Chart();
212 ChartBarType type3 = chart.createType("name3", Color.GREEN);
213 ChartBarType type2 = chart.createType("name2", Color.RED);
214 ChartBarType type1 = chart.createType("name1", Color.BLACK);
215 chart.addBar(1, 2, 3, type1, "label1");
216 chart.addBar(2, 3, 4, type2, "label2");
217 chart.addBar(2, 4, 5, type3, "label3");
218 chart.addBar(3, 3, 4, type2, "label4");
219 chart.addBar(3, 4, 5, type3, "label5");
220 chart.addBar(3, 5, 6, type3, "label6");
221
222 TestingChartVisitor visitor = new TestingChartVisitor();
223 chart.accept(visitor);
lberkibf6ef0f2017-05-29 11:00:40 +0200224 assertThat(visitor.beginChartCount).isEqualTo(1);
225 assertThat(visitor.endChartCount).isEqualTo(1);
226 assertThat(visitor.rowCount).isEqualTo(3);
227 assertThat(visitor.barCount).isEqualTo(6);
228 assertThat(visitor.columnCount).isEqualTo(0);
229 assertThat(visitor.lineCount).isEqualTo(0);
Florian Weikert2be2f382015-12-07 15:02:00 +0000230 }
231
232 private ProfileInfo createProfileInfo(Runnable runnable, int noOfRows) throws Exception {
233 Scratch scratch = new Scratch();
234 Path cacheDir = scratch.dir("/tmp");
235 Path cacheFile = cacheDir.getRelative("profile1.dat");
236 Profiler profiler = Profiler.instance();
237 profiler.start(ProfiledTaskKinds.ALL, cacheFile.getOutputStream(), "basic test", false,
238 BlazeClock.instance(), BlazeClock.instance().nanoTime());
239
240 // Write from multiple threads to generate multiple rows in the chart.
241 for (int i = 0; i < noOfRows; i++) {
242 Thread t = new Thread(runnable);
243 t.start();
244 t.join();
245 }
246
247 profiler.stop();
248 return ProfileInfo.loadProfile(cacheFile);
249 }
250
251 private void task(final Profiler profiler, ProfilerTask task, String name) {
252 profiler.startTask(task, name);
253 try {
254 Thread.sleep(100);
255 } catch (InterruptedException e) {
256 // ignore
257 }
258 profiler.completeTask(task);
259 }
260
261 private static final class TestingChartVisitor implements ChartVisitor {
262 private int rowCount;
263 private int endChartCount;
264 private int barCount;
265 private int beginChartCount;
266 private int columnCount;
267 private int lineCount;
268
269 @Override
270 public void visit(Chart chart) {
271 beginChartCount++;
272 }
273
274 @Override
275 public void endVisit(Chart chart) {
276 endChartCount++;
277 }
278
279 @Override
280 public void visit(ChartRow chartRow) {
281 rowCount++;
282 }
283
284 @Override
285 public void visit(ChartBar chartBar) {
286 barCount++;
287 }
288
289 @Override
290 public void visit(ChartColumn chartColumn) {
291 columnCount++;
292 }
293
294 @Override
295 public void visit(ChartLine chartLine) {
296 lineCount++;
297 }
298 }
299}