Index: pkg/compiler/lib/src/common/tasks.dart |
diff --git a/pkg/compiler/lib/src/common/tasks.dart b/pkg/compiler/lib/src/common/tasks.dart |
index 42d5e7b9b0a184f1d4a98fbf27a55e010f1386fd..c28783bfd52781494f5cc1c6cb1ee4d84c7cc3d2 100644 |
--- a/pkg/compiler/lib/src/common/tasks.dart |
+++ b/pkg/compiler/lib/src/common/tasks.dart |
@@ -7,43 +7,37 @@ library dart2js.common.tasks; |
import 'dart:async' |
show Future, Zone, ZoneDelegate, ZoneSpecification, runZoned; |
-import '../common.dart'; |
-import '../compiler.dart' show Compiler; |
-import '../elements/elements.dart' show Element; |
- |
-typedef void DeferredAction(); |
- |
-class DeferredTask { |
Siggi Cherem (dart-lang)
2016/05/25 01:45:17
this is unrelated to the other kind of task, I mov
Johnni Winther
2016/05/25 09:02:00
Acknowledged.
|
- final Element element; |
- final DeferredAction action; |
- |
- DeferredTask(this.element, this.action); |
-} |
- |
-/// A [CompilerTask] is used to measure where time is spent in the compiler. |
-/// The main entry points are [measure] and [measureIo]. |
-class CompilerTask { |
- final Compiler compiler; |
- final Stopwatch watch; |
+/// Used to measure where time is spent in the compiler. |
+/// |
+/// This exposes [measure] and [measureIo], which wrap an action and assotiate |
Harry Terkelsen
2016/05/25 15:51:36
assotiate -> associate
Siggi Cherem (dart-lang)
2016/05/25 16:11:18
Done.
|
+/// the time spend during that action with this task. Nested measurements can be |
Harry Terkelsen
2016/05/25 15:51:36
spend -> spent
Siggi Cherem (dart-lang)
2016/05/25 16:11:17
Done.
|
+/// introduced by using [measureSubtask]. |
+// TODO(sigmund): rename to MeasurableTask |
+abstract class CompilerTask { |
+ final Measurer measurer; |
+ final Stopwatch _watch; |
final Map<String, GenericTask> _subtasks = <String, GenericTask>{}; |
int asyncCount = 0; |
- CompilerTask(Compiler compiler) |
- : this.compiler = compiler, |
- watch = (compiler.options.verbose) ? new Stopwatch() : null; |
+ CompilerTask(Measurer measurer) |
+ : measurer = measurer, |
+ _watch = measurer.enableTaskMeasurements ? new Stopwatch() : null; |
- DiagnosticReporter get reporter => compiler.reporter; |
- |
- Measurer get measurer => compiler.measurer; |
+ /// Whether measurement is disabled. The functions [measure] and [measureIo] |
+ /// only measure time if measurements are enabled. |
+ bool get _isDisabled => _watch == null; |
+ /// Name to use for reporting timing information. |
+ // Note: it would be sufficient to mark this getter abstract if we had enough |
Harry Terkelsen
2016/05/25 15:51:36
this note seems more like a TODO
Siggi Cherem (dart-lang)
2016/05/25 16:11:17
Yeah, not sure if it's worth deleting. Rephrase th
|
+ // static checking to ensure that all subclasses override it. |
String get name => "Unknown task '${this.runtimeType}'"; |
- bool get isRunning => watch?.isRunning == true; |
+ bool get isRunning => _watch?.isRunning == true; |
int get timing { |
- if (watch == null) return 0; |
- int total = watch.elapsedMilliseconds; |
+ if (_isDisabled) return 0; |
+ int total = _watch.elapsedMilliseconds; |
for (GenericTask subtask in _subtasks.values) { |
total += subtask.timing; |
} |
@@ -51,40 +45,40 @@ class CompilerTask { |
} |
Duration get duration { |
- if (watch == null) return Duration.ZERO; |
- Duration total = watch.elapsed; |
+ if (_isDisabled) return Duration.ZERO; |
+ Duration total = _watch.elapsed; |
for (GenericTask subtask in _subtasks.values) { |
total += subtask.duration; |
} |
return total; |
} |
- /// Perform [action] and use [watch] to measure its runtime (including any |
+ /// Perform [action] and use [_watch] to measure its runtime (including any |
Harry Terkelsen
2016/05/25 15:51:36
maybe remove the part about _watch in the docs sin
Siggi Cherem (dart-lang)
2016/05/25 16:11:18
good point, done.
|
/// asynchronous callbacks, such as, [Future.then], but excluding code |
/// measured by other tasks). |
- measure(action()) => watch == null ? action() : measureZoned(action); |
+ measure(action()) => _isDisabled ? action() : _measureZoned(action); |
/// Helper method that starts measuring with this [CompilerTask], that is, |
/// make this task the currently measured task. |
- CompilerTask start() { |
- if (watch == null) return null; |
+ CompilerTask _start() { |
+ if (_isDisabled) return null; |
CompilerTask previous = measurer.currentTask; |
measurer.currentTask = this; |
- if (previous != null) previous.watch.stop(); |
+ if (previous != null) previous._watch.stop(); |
// Regardless of whether [previous] is `null` we've returned from the |
// eventloop. |
measurer.stopAsyncWallClock(); |
- watch.start(); |
+ _watch.start(); |
return previous; |
} |
/// Helper method that stops measuring with this [CompilerTask], that is, |
/// make [previous] the currently measured task. |
- void stop(CompilerTask previous) { |
- if (watch == null) return; |
- watch.stop(); |
+ void _stop(CompilerTask previous) { |
+ if (_isDisabled) return; |
+ _watch.stop(); |
if (previous != null) { |
- previous.watch.start(); |
+ previous._watch.start(); |
} else { |
// If there's no previous task, we're about to return control to the |
// event loop. Start counting that as waiting asynchronous I/O. |
@@ -93,55 +87,53 @@ class CompilerTask { |
measurer.currentTask = previous; |
} |
- /// Helper method for [measure]. Don't call this method directly as it |
- /// assumes that [watch] isn't null. |
- measureZoned(action()) { |
+ _measureZoned(action()) { |
// Using zones, we're able to track asynchronous operations correctly, as |
// our zone will be asked to invoke `then` blocks. Then blocks (the closure |
// passed to runZoned, and other closures) are run via the `run` functions |
// below. |
- assert(watch != null); |
+ assert(_watch != null); |
// The current zone is already measuring `this` task. |
if (Zone.current[measurer] == this) return action(); |
/// Run [f] in [zone]. Running must be delegated to [parent] to ensure that |
/// various state is set up correctly (in particular that `Zone.current` |
- /// has the right value). Since [measureZoned] can be called recursively |
+ /// has the right value). Since [_measureZoned] can be called recursively |
/// (synchronously), some of the measuring zones we create will be parents |
/// of other measuring zones, but we still need to call through the parent |
/// chain. Consequently, we use a zone value keyed by [measurer] to see if |
/// we should measure or not when delegating. |
run(Zone self, ZoneDelegate parent, Zone zone, f()) { |
if (zone[measurer] != this) return parent.run(zone, f); |
- CompilerTask previous = start(); |
+ CompilerTask previous = _start(); |
try { |
return parent.run(zone, f); |
} finally { |
- stop(previous); |
+ _stop(previous); |
} |
} |
/// Same as [run] except that [f] takes one argument, [arg]. |
runUnary(Zone self, ZoneDelegate parent, Zone zone, f(arg), arg) { |
if (zone[measurer] != this) return parent.runUnary(zone, f, arg); |
- CompilerTask previous = start(); |
+ CompilerTask previous = _start(); |
try { |
return parent.runUnary(zone, f, arg); |
} finally { |
- stop(previous); |
+ _stop(previous); |
} |
} |
/// Same as [run] except that [f] takes two arguments ([a1] and [a2]). |
runBinary(Zone self, ZoneDelegate parent, Zone zone, f(a1, a2), a1, a2) { |
if (zone[measurer] != this) return parent.runBinary(zone, f, a1, a2); |
- CompilerTask previous = start(); |
+ CompilerTask previous = _start(); |
try { |
return parent.runBinary(zone, f, a1, a2); |
} finally { |
- stop(previous); |
+ _stop(previous); |
} |
} |
@@ -159,13 +151,8 @@ class CompilerTask { |
/// provider, but it could be used by other tasks as long as the input |
/// provider will not be called by those tasks. |
measureIo(Future action()) { |
- return watch == null ? action() : measureIoHelper(action); |
- } |
+ if (_isDisabled) return action(); |
- /// Helper method for [measureIo]. Don't call this directly as it assumes |
- /// that [watch] isn't null. |
- Future measureIoHelper(Future action()) { |
- assert(watch != null); |
if (measurer.currentAsyncTask == null) { |
measurer.currentAsyncTask = this; |
} else if (measurer.currentAsyncTask != this) { |
@@ -179,36 +166,16 @@ class CompilerTask { |
}); |
} |
- /// Convenience function for combining |
- /// [DiagnosticReporter.withCurrentElement] and [measure]. |
- measureElement(Element element, action()) { |
- return watch == null |
- ? reporter.withCurrentElement(element, action) |
- : measureElementHelper(element, action); |
- } |
- |
- /// Helper method for [measureElement]. Don't call this directly as it |
- /// assumes that [watch] isn't null. |
- measureElementHelper(Element element, action()) { |
- assert(watch != null); |
- return reporter.withCurrentElement(element, () => measure(action)); |
- } |
- |
/// Measure the time spent in [action] (if in verbose mode) and accumulate it |
/// under a subtask with the given name. |
measureSubtask(String name, action()) { |
- return watch == null ? action() : measureSubtaskHelper(name, action); |
- } |
+ if (_isDisabled) return action(); |
- /// Helper method for [measureSubtask]. Don't call this directly as it |
- /// assumes that [watch] isn't null. |
- measureSubtaskHelper(String name, action()) { |
- assert(watch != null); |
// Use a nested CompilerTask for the measurement to ensure nested [measure] |
// calls work correctly. The subtasks will never themselves have nested |
// subtasks because they are not accessible outside. |
GenericTask subtask = |
- _subtasks.putIfAbsent(name, () => new GenericTask(name, compiler)); |
+ _subtasks.putIfAbsent(name, () => new GenericTask(name, measurer)); |
return subtask.measure(action); |
} |
@@ -217,24 +184,36 @@ class CompilerTask { |
int getSubtaskTime(String subtask) => _subtasks[subtask].timing; |
bool getSubtaskIsRunning(String subtask) => _subtasks[subtask].isRunning; |
+ |
+ /// Used by the dart2js_incremental to provide measurements on each |
+ /// incremental compile. |
+ clearMeasurements() { |
+ if (_isDisabled) return; |
+ _watch.reset(); |
+ _subtasks.values.forEach((s) => s.clearMeasurements()); |
+ } |
} |
class GenericTask extends CompilerTask { |
final String name; |
- |
- GenericTask(this.name, Compiler compiler) : super(compiler); |
+ GenericTask(this.name, Measurer measurer) : super(measurer); |
} |
class Measurer { |
/// Measures the total runtime from this object was constructed. |
/// |
- /// Note: MUST be first field to ensure [wallclock] is started before other |
- /// computations. |
+ /// Note: MUST be the first field of this class to ensure [wallclock] is |
+ /// started before other computations. |
final Stopwatch wallClock = new Stopwatch()..start(); |
/// Measures gaps between zoned closures due to asynchronicity. |
final Stopwatch asyncWallClock = new Stopwatch(); |
+ /// Whether measurement of tasks is enabled. |
+ final bool enableTaskMeasurements; |
+ |
+ Measurer({this.enableTaskMeasurements: false}); |
+ |
/// The currently running task, that is, the task whose [Stopwatch] is |
/// currently running. |
CompilerTask currentTask; |
@@ -255,7 +234,7 @@ class Measurer { |
/// Call this before returning to the eventloop. |
void startAsyncWallClock() { |
if (currentAsyncTask != null) { |
- currentAsyncTask.watch.start(); |
+ currentAsyncTask._watch.start(); |
} else { |
asyncWallClock.start(); |
} |
@@ -264,7 +243,7 @@ class Measurer { |
/// Call this when the eventloop returns control to us. |
void stopAsyncWallClock() { |
if (currentAsyncTask != null) { |
- currentAsyncTask.watch.stop(); |
+ currentAsyncTask._watch.stop(); |
} |
asyncWallClock.stop(); |
} |