Chromium Code Reviews| Index: sdk/lib/developer/timeline.dart |
| diff --git a/sdk/lib/developer/timeline.dart b/sdk/lib/developer/timeline.dart |
| index 0b7cd41e6b8852544795335419037410933c3da5..c6a53a085764d9de24362ffd47ff3e52744b8e43 100644 |
| --- a/sdk/lib/developer/timeline.dart |
| +++ b/sdk/lib/developer/timeline.dart |
| @@ -9,12 +9,94 @@ const bool _isProduct = const bool.fromEnvironment("dart.vm.product"); |
| typedef dynamic TimelineSyncFunction(); |
| typedef Future TimelineAsyncFunction(); |
| +/// A class to represent Flow events. |
| +/// |
| +/// [Flow] objects are used to thread flow events between timeline slices, |
| +/// for example, those created with the [Timeline] class below. Adding |
| +/// [Flow] objects cause arrows to be drawn between slices in Chrome's trace |
| +/// viewer. The arrows start at e.g [Timeline] events that are passed a |
| +/// [Flow.begin] object, go through [Timeline] events that are passed a |
| +/// [Flow.step] object, and end at [Timeline] events that are passed a |
| +/// [Flow.end] object, all having the same [Flow.id]. For example: |
| +/// |
| +/// ```dart |
| +/// var flow = Flow.begin(); |
| +/// Timeline.timeSync('flow_test', () { |
| +/// doSomething(); |
| +/// }, flow: flow); |
| +/// |
| +/// Timeline.timeSync('flow_test', () { |
| +/// doSomething(); |
| +/// }, flow: Flow.step(flow.id)); |
| +/// |
| +/// Timeline.timeSync('flow_test', () { |
| +/// doSomething(); |
| +/// }, flow: Flow.end(flow.id)); |
| +/// ``` |
| +class Flow { |
| + // These values must be kept in sync with the enum "EventType" in |
| + // runtime/vm/timeline.h. |
| + static const int _begin = 9; |
| + static const int _step = 10; |
| + static const int _end = 11; |
| + |
| + final int _type; |
| + |
| + /// The flow id of the flow event. |
| + final int id; |
| + |
| + Flow._(this._type, this.id); |
| + |
| + /// A "begin" Flow event. |
| + /// |
| + /// When passed to a [Timeline] method, generates a "begin" Flow event. |
| + /// If [id] is not provided, an id that conflicts with no other Dart-generated |
| + /// flow id's will be generated. |
| + static Flow begin({int id}) { |
| + return new Flow._(_begin, id = id ?? _getNextAsyncId()); |
|
rmacnak
2017/07/28 20:27:54
Just `id ?? _getNextAsyncId()`. Don't need to writ
zra
2017/07/28 21:31:50
Done.
|
| + } |
| + |
| + /// A "step" Flow event. |
| + /// |
| + /// When passed to a [Timeline] method, generates a "step" Flow event. |
| + /// The [id] argument is required. It can come either from another [Flow] |
| + /// event, or some id that comes from the environment. |
| + static Flow step(int id) => new Flow._(_step, id); |
| + |
| + /// An "end" Flow event. |
| + /// |
| + /// When passed to a [Timeline] method, generates a "end" Flow event. |
| + /// The [id] argument is required. It can come either from another [Flow] |
| + /// event, or some id that comes from the environment. |
| + static Flow end(int id) => new Flow._(_end, id); |
| +} |
| + |
| /// Add to the timeline. |
| +/// |
| +/// [Timeline]'s methods add synchronous events to the timeline. When |
| +/// generating a timeline in Chrome's tracing format, using [Timeline] generates |
| +/// "Complete" events. [Timeline]'s [startSync] and [endSync] can be used |
| +/// explicitly, or implicitly by wrapping a closure in [timeSync]. For exmaple: |
| +/// |
| +/// ```dart |
| +/// Timeline.startSync("Doing Something"); |
| +/// doSomething(); |
| +/// Timeline.finishSync(); |
| +/// ``` |
| +/// |
| +/// Or: |
| +/// |
| +/// ```dart |
| +/// Timeline.timeSync("Doing Something", () { |
| +/// doSomething(); |
| +/// }); |
| +/// ``` |
| class Timeline { |
| /// Start a synchronous operation labeled [name]. Optionally takes |
| - /// a [Map] of [arguments]. This operation must be finished before |
| + /// a [Map] of [arguments]. This slice may also optionally be associated with |
| + /// a [Flow] event. This operation must be finished before |
| /// returning to the event queue. |
| - static void startSync(String name, {Map arguments}) { |
| + static void startSync(String name, {Map arguments, Flow flow}) { |
| if (_isProduct) { |
| return; |
| } |
| @@ -30,6 +112,9 @@ class Timeline { |
| if (arguments is Map) { |
| block._appendArguments(arguments); |
| } |
| + if (flow is Flow) { |
| + block.flow = flow; |
| + } |
| _stack.add(block); |
| } |
| @@ -74,8 +159,8 @@ class Timeline { |
| /// A utility method to time a synchronous [function]. Internally calls |
| /// [function] bracketed by calls to [startSync] and [finishSync]. |
| static dynamic timeSync(String name, TimelineSyncFunction function, |
| - {Map arguments}) { |
| - startSync(name, arguments: arguments); |
| + {Map arguments, Flow flow}) { |
| + startSync(name, arguments: arguments, flow: flow); |
| try { |
| return function(); |
| } finally { |
| @@ -225,6 +310,9 @@ class _SyncBlock { |
| // The start time stamp of the thread cpu clock. |
| final int _startCpu; |
| + /// An (optional) flow event associated with this block. |
| + Flow _flow; |
| + |
| _SyncBlock._(this.name, this._start, this._startCpu); |
| /// Finish this block of time. At this point, this block can no longer be |
| @@ -233,6 +321,10 @@ class _SyncBlock { |
| // Report event to runtime. |
| _reportCompleteEvent( |
| _start, _startCpu, category, name, _argumentsAsJson(_arguments)); |
| + if (_flow != null) { |
| + _reportFlowEvent(_start, _startCpu, category, name, _flow._type, _flow.id, |
| + _argumentsAsJson(_arguments)); |
|
rmacnak
2017/07/28 20:27:54
The arguments are already in the duration event, s
zra
2017/07/28 21:31:50
According to tests, it looks like I need to mainta
|
| + } |
| } |
| void _appendArguments(Map arguments) { |
| @@ -244,6 +336,10 @@ class _SyncBlock { |
| } |
| _arguments.addAll(arguments); |
| } |
| + |
| + void set flow(Flow f) { |
| + _flow = f; |
| + } |
| } |
| String _fastPathArguments; |
| @@ -283,6 +379,10 @@ external void _reportTaskEvent(int start, int taskId, String phase, |
| external void _reportCompleteEvent(int start, int startCpu, String category, |
| String name, String argumentsAsJson); |
| +/// Reports a flow event. |
| +external void _reportFlowEvent(int start, int startCpu, String category, |
| + String name, int type, int id, String argumentsAsJson); |
| + |
| /// Reports an instant event. |
| external void _reportInstantEvent( |
| int start, String category, String name, String argumentsAsJson); |