Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: lib/src/graph/transform_node.dart

Issue 1353013003: Add fine-grained logging for long running transformers. (Closed) Base URL: git@github.com:dart-lang/barback.git@master
Patch Set: Changelog entry Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « CHANGELOG.md ('k') | pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library barback.graph.transform_node; 5 library barback.graph.transform_node;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import '../asset/asset.dart'; 9 import '../asset/asset.dart';
10 import '../asset/asset_id.dart'; 10 import '../asset/asset_id.dart';
11 import '../asset/asset_node.dart'; 11 import '../asset/asset_node.dart';
12 import '../asset/asset_node_set.dart'; 12 import '../asset/asset_node_set.dart';
13 import '../errors.dart'; 13 import '../errors.dart';
14 import '../log.dart'; 14 import '../log.dart';
15 import '../transformer/aggregate_transform.dart'; 15 import '../transformer/aggregate_transform.dart';
16 import '../transformer/aggregate_transformer.dart'; 16 import '../transformer/aggregate_transformer.dart';
17 import '../transformer/declaring_aggregate_transform.dart'; 17 import '../transformer/declaring_aggregate_transform.dart';
18 import '../transformer/declaring_aggregate_transformer.dart'; 18 import '../transformer/declaring_aggregate_transformer.dart';
19 import '../transformer/lazy_aggregate_transformer.dart'; 19 import '../transformer/lazy_aggregate_transformer.dart';
20 import '../utils.dart'; 20 import '../utils.dart';
21 import 'node_status.dart'; 21 import 'node_status.dart';
22 import 'node_streams.dart'; 22 import 'node_streams.dart';
23 import 'phase.dart'; 23 import 'phase.dart';
24 import 'transformer_classifier.dart'; 24 import 'transformer_classifier.dart';
25 25
26 /// Every `_applyLogDuration`, we will issue a fine log entry letting the user
27 /// know that the transform is still executing.
28 const _applyLogDuration = const Duration(seconds: 10);
29
26 /// Describes a transform on a set of assets and its relationship to the build 30 /// Describes a transform on a set of assets and its relationship to the build
27 /// dependency graph. 31 /// dependency graph.
28 /// 32 ///
29 /// Keeps track of whether it's dirty and needs to be run and which assets it 33 /// Keeps track of whether it's dirty and needs to be run and which assets it
30 /// depends on. 34 /// depends on.
31 class TransformNode { 35 class TransformNode {
32 /// The aggregate key for this node. 36 /// The aggregate key for this node.
33 final String key; 37 final String key;
34 38
35 /// The [TransformerClassifier] that [this] belongs to. 39 /// The [TransformerClassifier] that [this] belongs to.
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 168
165 /// The controller for the currently-running [AggregateTransformer.apply] 169 /// The controller for the currently-running [AggregateTransformer.apply]
166 /// call's [AggregateTransform]. 170 /// call's [AggregateTransform].
167 /// 171 ///
168 /// This will be non-`null` when [AggregateTransform.apply] is running, which 172 /// This will be non-`null` when [AggregateTransform.apply] is running, which
169 /// means that it's always non-`null` when [_state] is [_State.APPLYING] or 173 /// means that it's always non-`null` when [_state] is [_State.APPLYING] or
170 /// [_State.NEEDS_APPLY], sometimes non-`null` when it's 174 /// [_State.NEEDS_APPLY], sometimes non-`null` when it's
171 /// [_State.NEEDS_DECLARE], and always `null` otherwise. 175 /// [_State.NEEDS_DECLARE], and always `null` otherwise.
172 AggregateTransformController _applyController; 176 AggregateTransformController _applyController;
173 177
174 /// The number of secondary inputs that have been requested but not yet 178 /// Map to track pending requests for secondary inputs.
175 /// produced. 179 ///
176 int _pendingSecondaryInputs = 0; 180 /// Keys are the secondary inputs that have been requested but not yet
181 /// produced. Values are the number of requests for that input.
182 final _pendingSecondaryInputs = <AssetId, int>{};
177 183
178 /// A stopwatch that tracks the total time spent in a transformer's `apply` 184 /// A stopwatch that tracks the total time spent in a transformer's `apply`
179 /// function. 185 /// function.
180 final _timeInTransformer = new Stopwatch(); 186 final _timeInTransformer = new Stopwatch();
181 187
182 /// A stopwatch that tracks the time in a transformer's `apply` function spent 188 /// A stopwatch that tracks the time in a transformer's `apply` function spent
183 /// waiting for [getInput] calls to complete. 189 /// waiting for [getInput] calls to complete.
184 final _timeAwaitingInputs = new Stopwatch(); 190 final _timeAwaitingInputs = new Stopwatch();
185 191
186 TransformNode(this.classifier, this.transformer, this.key, this._location) { 192 TransformNode(this.classifier, this.transformer, this.key, this._location) {
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 _state = _State.APPLIED; 576 _state = _State.APPLIED;
571 _streams.changeStatus(NodeStatus.IDLE); 577 _streams.changeStatus(NodeStatus.IDLE);
572 }); 578 });
573 } 579 }
574 580
575 /// Gets the asset for an input [id]. 581 /// Gets the asset for an input [id].
576 /// 582 ///
577 /// If an input with [id] cannot be found, throws an [AssetNotFoundException]. 583 /// If an input with [id] cannot be found, throws an [AssetNotFoundException].
578 Future<Asset> getInput(AssetId id) { 584 Future<Asset> getInput(AssetId id) {
579 _timeAwaitingInputs.start(); 585 _timeAwaitingInputs.start();
580 _pendingSecondaryInputs++; 586 _pendingSecondaryInputs[id] = _pendingSecondaryInputs.containsKey(id)
587 ? _pendingSecondaryInputs[id] + 1
588 : 1;
581 return phase.previous.getOutput(id).then((node) { 589 return phase.previous.getOutput(id).then((node) {
582 // Throw if the input isn't found. This ensures the transformer's apply 590 // Throw if the input isn't found. This ensures the transformer's apply
583 // is exited. We'll then catch this and report it through the proper 591 // is exited. We'll then catch this and report it through the proper
584 // results stream. 592 // results stream.
585 if (node == null) { 593 if (node == null) {
586 _missingInputs.add(id); 594 _missingInputs.add(id);
587 595
588 // If this id is for an asset in another package, subscribe to that 596 // If this id is for an asset in another package, subscribe to that
589 // package's asset cascade so when it starts emitting the id we know to 597 // package's asset cascade so when it starts emitting the id we know to
590 // re-run the transformer. 598 // re-run the transformer.
(...skipping 12 matching lines...) Expand all
603 611
604 throw new AssetNotFoundException(id); 612 throw new AssetNotFoundException(id);
605 } 613 }
606 614
607 _secondarySubscriptions.putIfAbsent(node.id, () { 615 _secondarySubscriptions.putIfAbsent(node.id, () {
608 return node.onStateChange.listen((_) => _dirty()); 616 return node.onStateChange.listen((_) => _dirty());
609 }); 617 });
610 618
611 return node.asset; 619 return node.asset;
612 }).whenComplete(() { 620 }).whenComplete(() {
613 _pendingSecondaryInputs--; 621 assert(_pendingSecondaryInputs.containsKey(id));
614 if (_pendingSecondaryInputs != 0) _timeAwaitingInputs.stop(); 622 if (_pendingSecondaryInputs[id] == 1) {
623 _pendingSecondaryInputs.remove(id);
624 } else {
625 _pendingSecondaryInputs[id]--;
626 }
627 if (_pendingSecondaryInputs.isEmpty) _timeAwaitingInputs.stop();
615 }); 628 });
616 } 629 }
617 630
618 /// Run [AggregateTransformer.apply]. 631 /// Run [AggregateTransformer.apply].
619 /// 632 ///
620 /// Returns whether or not an error occurred while running the transformer. 633 /// Returns whether or not an error occurred while running the transformer.
621 Future<bool> _runApply() { 634 Future<bool> _runApply() {
622 var controller = new AggregateTransformController(this); 635 var controller = new AggregateTransformController(this);
623 _applyController = controller; 636 _applyController = controller;
624 _streams.onLogPool.add(controller.onLog); 637 _streams.onLogPool.add(controller.onLog);
625 for (var primary in _primaries) { 638 for (var primary in _primaries) {
626 if (!primary.state.isAvailable) continue; 639 if (!primary.state.isAvailable) continue;
627 controller.addInput(primary.asset); 640 controller.addInput(primary.asset);
628 } 641 }
629 _maybeFinishApplyController(); 642 _maybeFinishApplyController();
630 643
644 var transformCounterTimer;
645
631 return syncFuture(() { 646 return syncFuture(() {
632 _timeInTransformer.reset(); 647 _timeInTransformer.reset();
633 _timeAwaitingInputs.reset(); 648 _timeAwaitingInputs.reset();
634 _timeInTransformer.start(); 649 _timeInTransformer.start();
650
651 transformCounterTimer = new Timer.periodic(_applyLogDuration, (_) {
652 if (_streams.onLogController.isClosed ||
653 !_timeInTransformer.isRunning) {
654 return;
655 }
656
657 var message = new StringBuffer("Not yet complete after "
658 "${niceDuration(_timeInTransformer.elapsed)}");
659 if (_pendingSecondaryInputs.isNotEmpty) {
660 message.write(", waiting on input(s) "
661 "${_pendingSecondaryInputs.keys.join(", ")}");
662 }
663 _streams.onLogController.add(new LogEntry(
664 info,
665 info.primaryId,
666 LogLevel.FINE,
667 message.toString(),
668 null));
669 });
670
635 return transformer.apply(controller.transform); 671 return transformer.apply(controller.transform);
636 }).whenComplete(() { 672 }).whenComplete(() {
673 transformCounterTimer.cancel();
637 _timeInTransformer.stop(); 674 _timeInTransformer.stop();
638 _timeAwaitingInputs.stop(); 675 _timeAwaitingInputs.stop();
639 676
640 // Cancel the controller here even if `apply` wasn't interrupted. Since 677 // Cancel the controller here even if `apply` wasn't interrupted. Since
641 // the apply is finished, we want to close out the controller's streams. 678 // the apply is finished, we want to close out the controller's streams.
642 controller.cancel(); 679 controller.cancel();
643 _applyController = null; 680 _applyController = null;
644 }).then((_) { 681 }).then((_) {
645 assert(_state != _State.DECLARED); 682 assert(_state != _State.DECLARED);
646 assert(_state != _State.DECLARING); 683 assert(_state != _State.DECLARING);
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 /// declaring and [APPLYING] otherwise. If a primary input is added or 914 /// declaring and [APPLYING] otherwise. If a primary input is added or
878 /// removed, this will transition to [DECLARING]. 915 /// removed, this will transition to [DECLARING].
879 static const APPLIED = const _State._("applied"); 916 static const APPLIED = const _State._("applied");
880 917
881 final String name; 918 final String name;
882 919
883 const _State._(this.name); 920 const _State._(this.name);
884 921
885 String toString() => name; 922 String toString() => name;
886 } 923 }
OLDNEW
« no previous file with comments | « CHANGELOG.md ('k') | pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698