Skip to content

Commit d3d124a

Browse files
committed
Add logging of the compile step.
1 parent e4091bc commit d3d124a

File tree

7 files changed

+139
-7
lines changed

7 files changed

+139
-7
lines changed

build_runner/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 2.11.0-wip
2+
3+
- Add logging of builder compilation so you can tell how much time is spent
4+
on the JIT or AOT compile.
5+
16
## 2.10.3
27

38
- Performance: improve scalability with the number of library cycles, making

build_runner/lib/src/bootstrap/bootstrapper.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ class Bootstrapper {
5959

6060
// Compile if there was any change.
6161
if (!_compiler.checkFreshness(digestsAreFresh: false).outputIsFresh) {
62-
final result = await _compiler.compile(experiments: experiments);
62+
final result = await buildLog.logCompile(
63+
isAot: compileAot,
64+
function: () => _compiler.compile(experiments: experiments),
65+
);
6366
if (!result.succeeded) {
6467
final bool failedDueToMirrors;
6568
if (result.messages == null) {
@@ -109,6 +112,8 @@ class Bootstrapper {
109112
if (exitCode != ExitCode.tempFail.code) {
110113
return exitCode;
111114
}
115+
116+
buildLog.nextBuild(recompilingBuilders: true);
112117
}
113118
}
114119

build_runner/lib/src/bootstrap/build_process_state.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,20 @@ class BuildProcessState {
4545
set elapsedMillis(int elapsedMillis) =>
4646
_state['elapsedMillis'] = elapsedMillis;
4747

48+
// For `buildLog`, the JIT compile progress.
49+
Object? get jitCompileProgress => _state['jitCompileProgress'];
50+
set jitCompileProgress(Object? jitCompileProgress) =>
51+
_state['jitCompileProgress'] = jitCompileProgress;
52+
53+
// For `buildLog`, the AOT compile progress.
54+
Object? get aotCompileProgress => _state['aotCompileProgress'];
55+
set aotCompileProgress(Object? aotCompileProgress) =>
56+
_state['aotCompileProgress'] = aotCompileProgress;
57+
58+
// For `buildLog`, the build number.
59+
int get buildNumber => _state['buildNumber'] as int? ?? 1;
60+
set buildNumber(int buildNumber) => _state['buildNumber'] = buildNumber;
61+
4862
/// The package config URI.
4963
String get packageConfigUri =>
5064
(_state['packageConfigUri'] ??= Isolate.packageConfigSync!.toString())

build_runner/lib/src/logging/build_log.dart

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'dart:async';
56
import 'dart:io';
67
import 'dart:math';
78

@@ -73,6 +74,12 @@ class BuildLog {
7374
/// Errors logged.
7475
final ListBuilder<String> _errors = ListBuilder();
7576

77+
/// JIT compile progress, if there was a JIT compile.
78+
_CompileProgress? _jitCompileProgress;
79+
80+
/// AOT compile progress, if there was an AOT compile.
81+
_CompileProgress? _aotCompileProgress;
82+
7683
/// Progress by build phase.
7784
final Map<String, _PhaseProgress> _phaseProgress = {};
7885

@@ -102,6 +109,9 @@ class BuildLog {
102109
buildProcessState.doBeforeSend(() {
103110
buildProcessState.elapsedMillis = _processDuration.inMilliseconds;
104111
buildProcessState.buildLogMode = configuration.mode;
112+
buildProcessState.jitCompileProgress = _jitCompileProgress?.serialize();
113+
buildProcessState.aotCompileProgress = _aotCompileProgress?.serialize();
114+
buildProcessState.buildNumber = _buildNumber;
105115
});
106116
void updateFromProcessState() {
107117
_processDuration = Duration(
@@ -110,6 +120,13 @@ class BuildLog {
110120
configuration = configuration.rebuild((b) {
111121
b.mode = buildProcessState.buildLogMode;
112122
});
123+
_jitCompileProgress = _CompileProgress.deserialize(
124+
buildProcessState.jitCompileProgress,
125+
);
126+
_aotCompileProgress = _CompileProgress.deserialize(
127+
buildProcessState.aotCompileProgress,
128+
);
129+
_buildNumber = buildProcessState.buildNumber;
113130
}
114131

115132
updateFromProcessState();
@@ -226,6 +243,54 @@ class BuildLog {
226243
);
227244
}
228245

246+
Future<T> logCompile<T>({
247+
required bool isAot,
248+
required Future<T> Function() function,
249+
}) async {
250+
final progress = _CompileProgress();
251+
if (isAot) {
252+
_aotCompileProgress = progress;
253+
} else {
254+
_jitCompileProgress = progress;
255+
}
256+
_compileTick(isAot: isAot, firstTick: true);
257+
258+
final timer = Timer.periodic(
259+
const Duration(milliseconds: 100),
260+
(_) => _compileTick(isAot: isAot, firstTick: false),
261+
);
262+
try {
263+
return await function();
264+
} finally {
265+
timer.cancel();
266+
}
267+
}
268+
269+
void _compileTick({required bool firstTick, required bool isAot}) {
270+
final duration = _stopwatch.elapsed;
271+
_stopwatch.reset();
272+
_processDuration += duration;
273+
274+
if (!firstTick) {
275+
if (isAot) {
276+
_aotCompileProgress!.duration += duration;
277+
} else {
278+
_jitCompileProgress!.duration += duration;
279+
}
280+
}
281+
282+
if (_shouldShowProgressNow) {
283+
if (_display.displayingBlocks) {
284+
_display.block(render());
285+
} else {
286+
_display.message(
287+
Severity.info,
288+
_renderCompiling(isAot: isAot).toString(),
289+
);
290+
}
291+
}
292+
}
293+
229294
/// Sets up logging of build phases with the number of primary inputs matching
230295
/// for each required phase.
231296
void startPhases(Map<InBuildPhase, int> primaryInputCountsByPhase) {
@@ -337,13 +402,16 @@ class BuildLog {
337402
/// build) has started.
338403
///
339404
/// Clears timings and messages.
340-
void nextBuild() {
405+
void nextBuild({bool recompilingBuilders = false}) {
341406
_stopwatch.reset();
342407
_processDuration = Duration.zero;
343408
activities.clear();
344409
_messages.clear();
345410
_status.clear();
346-
_display.flushAndPrint('\nStarting build #${++_buildNumber}.\n');
411+
_display.flushAndPrint(
412+
'\nStarting build #${++_buildNumber}'
413+
'${recompilingBuilders ? ' with updated builders' : ''}.\n',
414+
);
347415
}
348416

349417
/// Logs that the build has finished with [result] and the count of [outputs].
@@ -374,6 +442,10 @@ class BuildLog {
374442
);
375443
}
376444

445+
_processDuration = Duration.zero;
446+
_jitCompileProgress = null;
447+
_aotCompileProgress = null;
448+
377449
final errors = _errors.build();
378450
_errors.clear();
379451
return errors;
@@ -442,6 +514,13 @@ class BuildLog {
442514
AnsiBuffer render() {
443515
final result = AnsiBuffer();
444516

517+
if (_jitCompileProgress != null) {
518+
result.write(_renderCompiling(isAot: false));
519+
}
520+
if (_aotCompileProgress != null) {
521+
result.write(_renderCompiling(isAot: true));
522+
}
523+
445524
final displayedProgressEntries = _phaseProgress.entries.where(
446525
(e) => e.value.isDisplayed || _messages.hasMessages(phaseName: e.key),
447526
);
@@ -484,8 +563,20 @@ class BuildLog {
484563
return result;
485564
}
486565

566+
AnsiBufferLine _renderCompiling({required bool isAot}) {
567+
final progress = isAot ? _aotCompileProgress! : _jitCompileProgress!;
568+
return AnsiBufferLine([
569+
renderDuration(progress.duration),
570+
' ',
571+
AnsiBuffer.bold,
572+
'compiling builders',
573+
AnsiBuffer.reset,
574+
'/${isAot ? 'aot' : 'jit'}',
575+
]);
576+
}
577+
487578
/// Renders a line describing the progress of [phaseName].
488-
AnsiBufferLine _renderPhase(String phaseName, {int padDuration = 0}) {
579+
AnsiBufferLine _renderPhase(String phaseName) {
489580
final activities = this.activities.render(phaseName: phaseName);
490581

491582
var firstSeparator = true;
@@ -499,7 +590,7 @@ class BuildLog {
499590

500591
final progress = _phaseProgress[phaseName]!;
501592
return AnsiBufferLine([
502-
renderDuration(progress.duration).padLeft(padDuration),
593+
renderDuration(progress.duration),
503594
' ',
504595
AnsiBuffer.bold,
505596
phaseName,
@@ -554,6 +645,19 @@ extension _PhaseExtension on InBuildPhase {
554645
lazy ? '$displayName (lazy)' : displayName;
555646
}
556647

648+
/// Compile progress.
649+
class _CompileProgress {
650+
Duration duration = Duration.zero;
651+
652+
Object? serialize() => duration.inMilliseconds;
653+
654+
static _CompileProgress? deserialize(Object? serialized) {
655+
if (serialized == null) return null;
656+
return _CompileProgress()
657+
..duration = Duration(milliseconds: serialized as int);
658+
}
659+
}
660+
557661
/// Progress metrics tracked for each build phase.
558662
class _PhaseProgress {
559663
Duration duration = Duration.zero;

build_runner/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: build_runner
2-
version: 2.10.3
2+
version: 2.11.0-wip
33
description: A build system for Dart code generation and modular compilation.
44
repository: https://github.com/dart-lang/build/tree/master/build_runner
55
resolution: workspace

build_test/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 3.5.4-wip
2+
3+
- Use `build_runner` 2.11.0.
4+
15
## 3.5.3
26

37
- Use `build_runner` 2.10.3.

build_test/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ environment:
1010
dependencies:
1111
build: ^4.0.0
1212
build_config: ^1.0.0
13-
build_runner: '2.10.3'
13+
build_runner: '2.11.0-wip'
1414
built_collection: ^5.1.1
1515
crypto: ^3.0.0
1616
glob: ^2.0.0

0 commit comments

Comments
 (0)