Skip to content

Commit d26a4dd

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

File tree

9 files changed

+170
-7
lines changed

9 files changed

+170
-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: 113 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,59 @@ 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, lastTick: false);
257+
258+
final timer = Timer.periodic(
259+
const Duration(milliseconds: 100),
260+
(_) => _compileTick(isAot: isAot, firstTick: false, lastTick: false),
261+
);
262+
try {
263+
return await function();
264+
} finally {
265+
timer.cancel();
266+
_compileTick(isAot: isAot, firstTick: false, lastTick: true);
267+
}
268+
}
269+
270+
void _compileTick({
271+
required bool isAot,
272+
required bool firstTick,
273+
required bool lastTick,
274+
}) {
275+
final duration = _stopwatch.elapsed;
276+
_stopwatch.reset();
277+
_processDuration += duration;
278+
279+
if (!firstTick) {
280+
if (isAot) {
281+
_aotCompileProgress!.duration += duration;
282+
} else {
283+
_jitCompileProgress!.duration += duration;
284+
}
285+
}
286+
287+
if (_shouldShowProgressNow || lastTick) {
288+
if (_display.displayingBlocks) {
289+
_display.block(render());
290+
} else {
291+
_display.message(
292+
Severity.info,
293+
_renderCompiling(isAot: isAot).toString(),
294+
);
295+
}
296+
}
297+
}
298+
229299
/// Sets up logging of build phases with the number of primary inputs matching
230300
/// for each required phase.
231301
void startPhases(Map<InBuildPhase, int> primaryInputCountsByPhase) {
@@ -337,13 +407,16 @@ class BuildLog {
337407
/// build) has started.
338408
///
339409
/// Clears timings and messages.
340-
void nextBuild() {
410+
void nextBuild({bool recompilingBuilders = false}) {
341411
_stopwatch.reset();
342412
_processDuration = Duration.zero;
343413
activities.clear();
344414
_messages.clear();
345415
_status.clear();
346-
_display.flushAndPrint('\nStarting build #${++_buildNumber}.\n');
416+
_display.flushAndPrint(
417+
'\nStarting build #${++_buildNumber}'
418+
'${recompilingBuilders ? ' with updated builders' : ''}.\n',
419+
);
347420
}
348421

349422
/// Logs that the build has finished with [result] and the count of [outputs].
@@ -374,6 +447,10 @@ class BuildLog {
374447
);
375448
}
376449

450+
_processDuration = Duration.zero;
451+
_jitCompileProgress = null;
452+
_aotCompileProgress = null;
453+
377454
final errors = _errors.build();
378455
_errors.clear();
379456
return errors;
@@ -442,6 +519,13 @@ class BuildLog {
442519
AnsiBuffer render() {
443520
final result = AnsiBuffer();
444521

522+
if (_jitCompileProgress != null) {
523+
result.write(_renderCompiling(isAot: false));
524+
}
525+
if (_aotCompileProgress != null) {
526+
result.write(_renderCompiling(isAot: true));
527+
}
528+
445529
final displayedProgressEntries = _phaseProgress.entries.where(
446530
(e) => e.value.isDisplayed || _messages.hasMessages(phaseName: e.key),
447531
);
@@ -484,8 +568,20 @@ class BuildLog {
484568
return result;
485569
}
486570

571+
AnsiBufferLine _renderCompiling({required bool isAot}) {
572+
final progress = isAot ? _aotCompileProgress! : _jitCompileProgress!;
573+
return AnsiBufferLine([
574+
renderDuration(progress.duration),
575+
' ',
576+
AnsiBuffer.bold,
577+
'compiling builders',
578+
AnsiBuffer.reset,
579+
'/${isAot ? 'aot' : 'jit'}',
580+
]);
581+
}
582+
487583
/// Renders a line describing the progress of [phaseName].
488-
AnsiBufferLine _renderPhase(String phaseName, {int padDuration = 0}) {
584+
AnsiBufferLine _renderPhase(String phaseName) {
489585
final activities = this.activities.render(phaseName: phaseName);
490586

491587
var firstSeparator = true;
@@ -499,7 +595,7 @@ class BuildLog {
499595

500596
final progress = _phaseProgress[phaseName]!;
501597
return AnsiBufferLine([
502-
renderDuration(progress.duration).padLeft(padDuration),
598+
renderDuration(progress.duration),
503599
' ',
504600
AnsiBuffer.bold,
505601
phaseName,
@@ -554,6 +650,19 @@ extension _PhaseExtension on InBuildPhase {
554650
lazy ? '$displayName (lazy)' : displayName;
555651
}
556652

653+
/// Compile progress.
654+
class _CompileProgress {
655+
Duration duration = Duration.zero;
656+
657+
Object? serialize() => duration.inMilliseconds;
658+
659+
static _CompileProgress? deserialize(Object? serialized) {
660+
if (serialized == null) return null;
661+
return _CompileProgress()
662+
..duration = Duration(milliseconds: serialized as int);
663+
}
664+
}
665+
557666
/// Progress metrics tracked for each build phase.
558667
class _PhaseProgress {
559668
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_runner/test/logging/build_log_console_mode_test.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,22 @@ E An error.'''),
4444
);
4545
});
4646

47+
test('compile progress', () {
48+
buildLog.logCompile(isAot: false, function: () async {});
49+
expect(
50+
render(),
51+
padLinesRight('''
52+
0s compiling builders/jit'''),
53+
);
54+
buildLog.logCompile(isAot: true, function: () async {});
55+
expect(
56+
render(),
57+
padLinesRight('''
58+
0s compiling builders/jit
59+
0s compiling builders/aot'''),
60+
);
61+
});
62+
4763
test('phase progress', () {
4864
final phases = _createPhases({'builder1': 10, 'builder2': 15});
4965
buildLog.startPhases(phases);

build_runner/test/logging/build_log_line_mode_test.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ void main() {
3737
]);
3838
});
3939

40+
test('compile progress', () {
41+
buildLog.logCompile(isAot: false, function: () async {});
42+
expect(lines, [' 0s compiling builders/jit']);
43+
buildLog.logCompile(isAot: true, function: () async {});
44+
expect(lines, [
45+
' 0s compiling builders/jit',
46+
' 0s compiling builders/aot',
47+
]);
48+
});
49+
4050
test('phase progress', () {
4151
final phases = _createPhases({'builder1': 10, 'builder2': 15});
4252
buildLog.startPhases(phases);

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)