blob: ee2ca955e9f6e8f9b6a463eeff8484bc9ef8d845 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
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.runtime;
15
16import com.google.common.base.Joiner;
17import com.google.common.eventbus.EventBus;
18import com.google.common.eventbus.Subscribe;
janakr1fb90fd2017-03-30 21:07:04 +000019import com.google.devtools.build.lib.buildtool.BuildRequest;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010020import com.google.devtools.build.lib.buildtool.buildevent.BuildCompleteEvent;
21import com.google.devtools.build.lib.buildtool.buildevent.ExecutionStartingEvent;
22import com.google.devtools.build.lib.events.Event;
23import com.google.devtools.build.lib.events.Reporter;
janakr1fb90fd2017-03-30 21:07:04 +000024import com.google.devtools.build.lib.exec.ExecutionOptions;
25import com.google.devtools.build.lib.exec.ExecutorBuilder;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010026import com.google.devtools.build.lib.profiler.Profiler;
27import com.google.devtools.build.lib.profiler.ProfilerTask;
28import com.google.devtools.build.lib.util.BlazeClock;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010029import java.util.ArrayList;
30import java.util.List;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010031import java.util.logging.Logger;
32
33/**
34 * Blaze module for the build summary message that reports various stats to the user.
35 */
36public class BuildSummaryStatsModule extends BlazeModule {
37
38 private static final Logger LOG = Logger.getLogger(BuildSummaryStatsModule.class.getName());
39
40 private SimpleCriticalPathComputer criticalPathComputer;
41 private EventBus eventBus;
42 private Reporter reporter;
janakr1fb90fd2017-03-30 21:07:04 +000043 private boolean enabled;
janakr95d42802017-04-06 00:33:39 +000044 private boolean discardActions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010045
46 @Override
ulfjacka6a99102017-06-13 17:15:45 +020047 public void beforeCommand(CommandEnvironment env) {
Ulf Adams633f5392015-09-15 11:13:08 +000048 this.reporter = env.getReporter();
49 this.eventBus = env.getEventBus();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010050 eventBus.register(this);
51 }
52
Ulf Adams10efbf22016-04-18 11:35:25 +000053 @Override
54 public void afterCommand() {
55 this.criticalPathComputer = null;
56 this.eventBus = null;
57 this.reporter = null;
58 }
59
janakr1fb90fd2017-03-30 21:07:04 +000060 @Override
61 public void executorInit(CommandEnvironment env, BuildRequest request, ExecutorBuilder builder) {
62 enabled = env.getOptions().getOptions(ExecutionOptions.class).enableCriticalPathProfiling;
janakr95d42802017-04-06 00:33:39 +000063 discardActions = !env.getSkyframeExecutor().hasIncrementalState();
janakr1fb90fd2017-03-30 21:07:04 +000064 }
65
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010066 @Subscribe
67 public void executionPhaseStarting(ExecutionStartingEvent event) {
janakr1fb90fd2017-03-30 21:07:04 +000068 if (enabled) {
janakr95d42802017-04-06 00:33:39 +000069 criticalPathComputer = new SimpleCriticalPathComputer(BlazeClock.instance(), discardActions);
janakr1fb90fd2017-03-30 21:07:04 +000070 eventBus.register(criticalPathComputer);
71 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010072 }
73
74 @Subscribe
75 public void buildComplete(BuildCompleteEvent event) {
76 try {
77 // We might want to make this conditional on a flag; it can sometimes be a bit of a nuisance.
78 List<String> items = new ArrayList<>();
79 items.add(String.format("Elapsed time: %.3fs", event.getResult().getElapsedSeconds()));
80
81 if (criticalPathComputer != null) {
82 Profiler.instance().startTask(ProfilerTask.CRITICAL_PATH, "Critical path");
83 AggregatedCriticalPath<SimpleCriticalPathComponent> criticalPath =
84 criticalPathComputer.aggregate();
85 items.add(criticalPath.toStringSummary());
86 LOG.info(criticalPath.toString());
87 LOG.info("Slowest actions:\n " + Joiner.on("\n ")
88 .join(criticalPathComputer.getSlowestComponents()));
89 // We reverse the critical path because the profiler expect events ordered by the time
90 // when the actions were executed while critical path computation is stored in the reverse
91 // way.
92 for (SimpleCriticalPathComponent stat : criticalPath.components().reverse()) {
janakr95d42802017-04-06 00:33:39 +000093 Profiler.instance()
94 .logSimpleTaskDuration(
95 stat.getStartNanos(),
96 stat.getElapsedTimeNanos(),
97 ProfilerTask.CRITICAL_PATH_COMPONENT,
98 stat.prettyPrintAction());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010099 }
100 Profiler.instance().completeTask(ProfilerTask.CRITICAL_PATH);
101 }
102
103 reporter.handle(Event.info(Joiner.on(", ").join(items)));
104 } finally {
105 criticalPathComputer = null;
106 }
107 }
108}