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

Unified Diff: sdk/lib/developer/timeline.dart

Issue 1397823002: Add support for emitting asynchronous timeline events from Dart code (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/bootstrap_natives.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/developer/timeline.dart
diff --git a/sdk/lib/developer/timeline.dart b/sdk/lib/developer/timeline.dart
index 54c5b80f5ae89492bc667a170ee6d42f5a06b183..c42e5c0052bc0cce81f854ab901ff45b0ab4ab5d 100644
--- a/sdk/lib/developer/timeline.dart
+++ b/sdk/lib/developer/timeline.dart
@@ -32,8 +32,8 @@ class Timeline {
}
// Pop top item off of stack.
var block = _stack.removeLast();
- // Close it.
- block.close();
+ // Finish it.
+ block.finish();
}
/// A utility method to time a synchronous [function]. Internally calls
@@ -52,6 +52,130 @@ class Timeline {
static final List<_SyncBlock> _stack = new List<_SyncBlock>();
}
+/// An asynchronous task on the timeline. Asynchronous tasks can live
+/// longer than the current event and can even be shared between isolates.
+/// An asynchronous task can have many (nested) blocks. To share a
+/// [TimelineTask] across isolates, you must construct a [TimelineTask] in
+/// both isolates using the same [taskId] and [category].
+class TimelineTask {
+ /// Create a task. [taskId] will be set by the system.
+ /// Optionally you can specify a [category] name.
+ TimelineTask({String category: 'Dart'})
+ : _taskId = _getNextAsyncId(),
+ category = category {
+ if (category is! String) {
+ throw new ArgumentError.value(category,
+ 'category',
+ 'Must be a String');
+ }
+ }
+
+ /// Create a task with an explicit [taskId]. This is useful if you are
+ /// passing a task between isolates. Optionally you can specify a [category]
+ /// name.
+ TimelineTask.withTaskId(int taskId, {String category: 'Dart'})
+ : _taskId = taskId,
+ category = category {
+ if (taskId is! int) {
+ throw new ArgumentError.value(taskId,
+ 'taskId',
+ 'Must be an int');
+ }
+ if (category is! String) {
+ throw new ArgumentError.value(category,
+ 'category',
+ 'Must be a String');
+ }
+ }
+
+ /// Start a block in this task named [name]. Optionally takes
+ /// a [Map] of [arguments].
+ /// Returns an [AsyncBlock] which is used to finish this block.
+ AsyncBlock start(String name, {Map arguments}) {
+ if (name is! String) {
+ throw new ArgumentError.value(name,
+ 'name',
+ 'Must be a String');
+ }
+ var block = new AsyncBlock._(name, _taskId, category);
+ if (arguments is Map) {
+ block.arguments.addAll(arguments);
+ }
+ /// Emit start event.
+ block._start();
+ return block;
+ }
+
+ /// Retrieve the asynchronous task's id. Can be used to construct a
+ /// [TimelineTask] in another isolate.
+ int get taskId => _taskId;
+ final int _taskId;
+ /// Retrieve the asynchronous task's category. Can be used to construct a
+ /// [TimelineTask] in another isolate.
+ final String category;
+}
+
+/// An asynchronous block of time on the timeline. This block can be kept
+/// open across isolate messages.
+class AsyncBlock {
+ /// The category this block belongs to.
+ final String category;
+ /// The name of this block.
+ final String name;
+ /// The asynchronous task id.
+ final int _taskId;
+ /// An (optional) set of arguments which will be serialized to JSON and
+ /// associated with this block.
+ final Map arguments = {};
+ bool _finished = false;
+
+ AsyncBlock._(this.name, this._taskId, this.category);
+
+ // Emit the start event.
+ void _start() {
+ String argumentsAsJson = JSON.encode(arguments);
+ _reportTaskEvent(_getTraceClock(),
+ _taskId,
+ 'b',
+ category,
+ name,
+ argumentsAsJson);
+ }
+
+ // Emit the finish event.
+ void _finish() {
+ _reportTaskEvent(_getTraceClock(),
+ _taskId,
+ 'e',
+ category,
+ name,
+ JSON.encode({}));
+ }
+
+ /// Finish this block. Cannot be called twice.
+ void finish() {
+ if (_finished) {
+ throw new StateError(
+ 'It is illegal to call finish twice on the same AsyncBlock');
+ }
+ _finished = true;
+ _finish();
+ }
+
+ /// Finishes this block when [future] completes. Returns a [Future]
+ /// chained to [future].
+ Future finishWhenComplete(Future future) {
+ if (future is! Future) {
+ throw new ArgumentError.value(future,
+ 'future',
+ 'Must be a Future');
+ }
+ return future.whenComplete(() {
+ finish();
+ });
+ }
+}
+
/// A synchronous block of time on the timeline. This block should not be
/// kept open across isolate messages.
class _SyncBlock {
@@ -64,20 +188,13 @@ class _SyncBlock {
final Map arguments = {};
// The start time stamp.
final int _start;
- // Has this block been closed?
- bool _closed = false;
_SyncBlock._(this.name,
this._start);
- /// Close this block of time. At this point, this block can no longer be
+ /// Finish this block of time. At this point, this block can no longer be
/// used.
- void close() {
- if (_closed) {
- throw new StateError(
- 'It is illegal to call close twice on the same _SyncBlock');
- }
- _closed = true;
+ void finish() {
var end = _getTraceClock();
// Encode arguments map as JSON before reporting.
@@ -92,9 +209,20 @@ class _SyncBlock {
}
}
+/// Returns the next async task id.
+external int _getNextAsyncId();
+
/// Returns the current value from the trace clock.
external int _getTraceClock();
+/// Reports an event for a task.
+external void _reportTaskEvent(int start,
+ int taskId,
+ String phase,
+ String category,
+ String name,
+ String argumentsAsJson);
+
/// Reports a complete synchronous event.
external void _reportCompleteEvent(int start,
int end,
« no previous file with comments | « runtime/vm/bootstrap_natives.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698