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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « runtime/vm/bootstrap_natives.h ('k') | no next file » | 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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 part of dart.developer; 5 part of dart.developer;
6 6
7 typedef dynamic TimelineSyncFunction(); 7 typedef dynamic TimelineSyncFunction();
8 8
9 /// Add to the timeline. 9 /// Add to the timeline.
10 class Timeline { 10 class Timeline {
(...skipping 14 matching lines...) Expand all
25 } 25 }
26 26
27 /// Finish the last synchronous operation that was started. 27 /// Finish the last synchronous operation that was started.
28 static void finishSync() { 28 static void finishSync() {
29 if (_stack.length == 0) { 29 if (_stack.length == 0) {
30 throw new StateError( 30 throw new StateError(
31 'Uneven calls to startSync and finishSync'); 31 'Uneven calls to startSync and finishSync');
32 } 32 }
33 // Pop top item off of stack. 33 // Pop top item off of stack.
34 var block = _stack.removeLast(); 34 var block = _stack.removeLast();
35 // Close it. 35 // Finish it.
36 block.close(); 36 block.finish();
37 } 37 }
38 38
39 /// A utility method to time a synchronous [function]. Internally calls 39 /// A utility method to time a synchronous [function]. Internally calls
40 /// [function] bracketed by calls to [startSync] and [finishSync]. 40 /// [function] bracketed by calls to [startSync] and [finishSync].
41 static dynamic timeSync(String name, 41 static dynamic timeSync(String name,
42 TimelineSyncFunction function, 42 TimelineSyncFunction function,
43 {Map arguments}) { 43 {Map arguments}) {
44 startSync(name, arguments: arguments); 44 startSync(name, arguments: arguments);
45 try { 45 try {
46 return function(); 46 return function();
47 } finally { 47 } finally {
48 finishSync(); 48 finishSync();
49 } 49 }
50 } 50 }
51 51
52 static final List<_SyncBlock> _stack = new List<_SyncBlock>(); 52 static final List<_SyncBlock> _stack = new List<_SyncBlock>();
53 } 53 }
54 54
55 /// An asynchronous task on the timeline. Asynchronous tasks can live
56 /// longer than the current event and can even be shared between isolates.
57 /// An asynchronous task can have many (nested) blocks. To share a
58 /// [TimelineTask] across isolates, you must construct a [TimelineTask] in
59 /// both isolates using the same [taskId] and [category].
60 class TimelineTask {
61 /// Create a task. [taskId] will be set by the system.
62 /// Optionally you can specify a [category] name.
63 TimelineTask({String category: 'Dart'})
64 : _taskId = _getNextAsyncId(),
65 category = category {
66 if (category is! String) {
67 throw new ArgumentError.value(category,
68 'category',
69 'Must be a String');
70 }
71 }
72
73 /// Create a task with an explicit [taskId]. This is useful if you are
74 /// passing a task between isolates. Optionally you can specify a [category]
75 /// name.
76 TimelineTask.withTaskId(int taskId, {String category: 'Dart'})
77 : _taskId = taskId,
78 category = category {
79 if (taskId is! int) {
80 throw new ArgumentError.value(taskId,
81 'taskId',
82 'Must be an int');
83 }
84 if (category is! String) {
85 throw new ArgumentError.value(category,
86 'category',
87 'Must be a String');
88 }
89 }
90
91 /// Start a block in this task named [name]. Optionally takes
92 /// a [Map] of [arguments].
93 /// Returns an [AsyncBlock] which is used to finish this block.
94 AsyncBlock start(String name, {Map arguments}) {
95 if (name is! String) {
96 throw new ArgumentError.value(name,
97 'name',
98 'Must be a String');
99 }
100 var block = new AsyncBlock._(name, _taskId, category);
101 if (arguments is Map) {
102 block.arguments.addAll(arguments);
103 }
104 /// Emit start event.
105 block._start();
106 return block;
107 }
108
109 /// Retrieve the asynchronous task's id. Can be used to construct a
110 /// [TimelineTask] in another isolate.
111 int get taskId => _taskId;
112 final int _taskId;
113 /// Retrieve the asynchronous task's category. Can be used to construct a
114 /// [TimelineTask] in another isolate.
115 final String category;
116 }
117
118 /// An asynchronous block of time on the timeline. This block can be kept
119 /// open across isolate messages.
120 class AsyncBlock {
121 /// The category this block belongs to.
122 final String category;
123 /// The name of this block.
124 final String name;
125 /// The asynchronous task id.
126 final int _taskId;
127 /// An (optional) set of arguments which will be serialized to JSON and
128 /// associated with this block.
129 final Map arguments = {};
130 bool _finished = false;
131
132 AsyncBlock._(this.name, this._taskId, this.category);
133
134 // Emit the start event.
135 void _start() {
136 String argumentsAsJson = JSON.encode(arguments);
137 _reportTaskEvent(_getTraceClock(),
138 _taskId,
139 'b',
140 category,
141 name,
142 argumentsAsJson);
143 }
144
145 // Emit the finish event.
146 void _finish() {
147 _reportTaskEvent(_getTraceClock(),
148 _taskId,
149 'e',
150 category,
151 name,
152 JSON.encode({}));
153 }
154
155 /// Finish this block. Cannot be called twice.
156 void finish() {
157 if (_finished) {
158 throw new StateError(
159 'It is illegal to call finish twice on the same AsyncBlock');
160 }
161 _finished = true;
162 _finish();
163 }
164
165 /// Finishes this block when [future] completes. Returns a [Future]
166 /// chained to [future].
167 Future finishWhenComplete(Future future) {
168 if (future is! Future) {
169 throw new ArgumentError.value(future,
170 'future',
171 'Must be a Future');
172 }
173 return future.whenComplete(() {
174 finish();
175 });
176 }
177 }
178
55 /// A synchronous block of time on the timeline. This block should not be 179 /// A synchronous block of time on the timeline. This block should not be
56 /// kept open across isolate messages. 180 /// kept open across isolate messages.
57 class _SyncBlock { 181 class _SyncBlock {
58 /// The category this block belongs to. 182 /// The category this block belongs to.
59 final String category = 'Dart'; 183 final String category = 'Dart';
60 /// The name of this block. 184 /// The name of this block.
61 final String name; 185 final String name;
62 /// An (optional) set of arguments which will be serialized to JSON and 186 /// An (optional) set of arguments which will be serialized to JSON and
63 /// associated with this block. 187 /// associated with this block.
64 final Map arguments = {}; 188 final Map arguments = {};
65 // The start time stamp. 189 // The start time stamp.
66 final int _start; 190 final int _start;
67 // Has this block been closed?
68 bool _closed = false;
69 191
70 _SyncBlock._(this.name, 192 _SyncBlock._(this.name,
71 this._start); 193 this._start);
72 194
73 /// Close this block of time. At this point, this block can no longer be 195 /// Finish this block of time. At this point, this block can no longer be
74 /// used. 196 /// used.
75 void close() { 197 void finish() {
76 if (_closed) {
77 throw new StateError(
78 'It is illegal to call close twice on the same _SyncBlock');
79 }
80 _closed = true;
81 var end = _getTraceClock(); 198 var end = _getTraceClock();
82 199
83 // Encode arguments map as JSON before reporting. 200 // Encode arguments map as JSON before reporting.
84 var argumentsAsJson = JSON.encode(arguments); 201 var argumentsAsJson = JSON.encode(arguments);
85 202
86 // Report event to runtime. 203 // Report event to runtime.
87 _reportCompleteEvent(_start, 204 _reportCompleteEvent(_start,
88 end, 205 end,
89 category, 206 category,
90 name, 207 name,
91 argumentsAsJson); 208 argumentsAsJson);
92 } 209 }
93 } 210 }
94 211
212 /// Returns the next async task id.
213 external int _getNextAsyncId();
214
95 /// Returns the current value from the trace clock. 215 /// Returns the current value from the trace clock.
96 external int _getTraceClock(); 216 external int _getTraceClock();
97 217
218 /// Reports an event for a task.
219 external void _reportTaskEvent(int start,
220 int taskId,
221 String phase,
222 String category,
223 String name,
224 String argumentsAsJson);
225
98 /// Reports a complete synchronous event. 226 /// Reports a complete synchronous event.
99 external void _reportCompleteEvent(int start, 227 external void _reportCompleteEvent(int start,
100 int end, 228 int end,
101 String category, 229 String category,
102 String name, 230 String name,
103 String argumentsAsJson); 231 String argumentsAsJson);
OLDNEW
« 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