Index: sdk/lib/developer/timeline.dart |
diff --git a/sdk/lib/developer/timeline.dart b/sdk/lib/developer/timeline.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1f83ec73889e5fefd1216a19ea75e253c992078d |
--- /dev/null |
+++ b/sdk/lib/developer/timeline.dart |
@@ -0,0 +1,103 @@ |
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+part of dart.developer; |
+ |
+typedef dynamic TimelineSyncFunction(); |
+ |
+/// Add to the timeline. |
+class Timeline { |
+ /// Start a synchronous operation labeled [name]. Optionally takes |
+ /// a [Map] of [arguments]. This operation must be finished before |
+ /// returning to the event queue. |
+ static void startSync(String name, {Map arguments}) { |
+ if (name is! String) { |
+ throw new ArgumentError.value(name, |
+ 'name', |
+ 'Must be a String'); |
+ } |
+ var block = new _SyncBlock._(name, _getTraceClock()); |
+ if (arguments is Map) { |
+ block.arguments.addAll(arguments); |
+ } |
+ _stack.add(block); |
+ } |
+ |
+ /// Finish the last synchronous operation that was started. |
+ static void finishSync() { |
+ if (_stack.length == 0) { |
+ throw new StateError( |
+ 'Uneven calls to startSync and finishSync'); |
+ } |
+ // Pop top item off of stack. |
+ var block = _stack.removeLast(); |
+ // Close it. |
+ block.close(); |
+ } |
+ |
+ /// 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}) { |
+ beginSync(name, arguments: arguments); |
+ try { |
+ return function(); |
+ } finally { |
+ finishSync(); |
+ } |
+ } |
+ |
+ static final List<_SyncBlock> _stack = new List<_SyncBlock>(); |
+} |
+ |
+/// A synchronous block of time on the timeline. This block should not be |
+/// kept open across isolate messages. |
+class _SyncBlock { |
+ /// The category this block belongs to. |
+ final String category = 'Dart'; |
+ /// The name of this block. |
+ final String name; |
+ /// An (optional) set of arguments which will be serialized to JSON and |
+ /// associated with this block. |
+ 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 |
+ /// used. |
+ void close() { |
+ if (_closed) { |
+ throw new StateError( |
+ 'It is illegal to call close twice on the same _SyncBlock'); |
+ } |
+ _closed = true; |
+ var end = _getTraceClock(); |
+ |
+ // Encode arguments map as JSON before reporting. |
+ var argumentsAsJson = JSON.encode(arguments); |
+ |
+ // Report event to runtime. |
+ _reportCompleteEvent(_start, |
+ end, |
+ category, |
+ name, |
+ argumentsAsJson); |
+ } |
+} |
+ |
+/// Returns the current value from the trace clock. |
+external int _getTraceClock(); |
+ |
+/// Reports a complete synchronous event. |
+external void _reportCompleteEvent(int start, |
+ int end, |
+ String category, |
+ String name, |
+ String argumentsAsJson); |