diff options
author | sullivan@chromium.org <sullivan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-09 16:39:20 +0000 |
---|---|---|
committer | sullivan@chromium.org <sullivan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-09 16:39:20 +0000 |
commit | 042de4d1034c561c7135ee4d1a9fb9a75da07fef (patch) | |
tree | 21e18313edb2637368b126f9a16c45a52a56cccb /tools | |
parent | 515adc20f2278b0f9e777b3e20d2dcbb2560b2f3 (diff) | |
download | chromium_src-042de4d1034c561c7135ee4d1a9fb9a75da07fef.zip chromium_src-042de4d1034c561c7135ee4d1a9fb9a75da07fef.tar.gz chromium_src-042de4d1034c561c7135ee4d1a9fb9a75da07fef.tar.bz2 |
Revert 175782
> InspectorTimeline improvements
>
> - Split out inspector-neutral parts of InspectorTimeline in preparation for
> about:tracing-based timeline
> - Use event.name instead of type, which is in keeping with trace-viewer
> - Use ms on units since the rest of telemetry uses seconds, but
> for precision reasons, ms makes sense to stick with
> - Move arguments to event.args so that params get consistent treatment
> e.g. event.foo['bar'] is less consistent than event.args['foo']['bar']
> - Improved test coverage of model, events, parsing
> - event.self_time which represents
> - drop events lacking start- or end- times
>
> R=bulach@chromium.org
> NOTRY=True
>
> Review URL: https://chromiumcodereview.appspot.com/11818024
TBR=nduca@chromium.org
Review URL: https://codereview.chromium.org/11733008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@175810 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/perf_tools/image_decoding_benchmark.py | 8 | ||||
-rw-r--r-- | tools/telemetry/telemetry/inspector_timeline.py | 110 | ||||
-rw-r--r-- | tools/telemetry/telemetry/inspector_timeline_unittest.py | 143 | ||||
-rw-r--r-- | tools/telemetry/telemetry/timeline_event.py | 48 | ||||
-rw-r--r-- | tools/telemetry/telemetry/timeline_event_unittest.py | 27 | ||||
-rw-r--r-- | tools/telemetry/telemetry/timeline_model.py | 23 | ||||
-rw-r--r-- | tools/telemetry/telemetry/timeline_model_unittest.py | 18 |
7 files changed, 102 insertions, 275 deletions
diff --git a/tools/perf/perf_tools/image_decoding_benchmark.py b/tools/perf/perf_tools/image_decoding_benchmark.py index 00d0d40..c0df84e 100644 --- a/tools/perf/perf_tools/image_decoding_benchmark.py +++ b/tools/perf/perf_tools/image_decoding_benchmark.py @@ -15,7 +15,7 @@ class ImageDecoding(multi_page_benchmark.MultiPageBenchmark): return tab.runtime.Evaluate('isDone') decode_image_events = \ - tab.timeline.timeline_events.GetAllOfName('DecodeImage') + tab.timeline.timeline_events.GetAllOfType('DecodeImage') # If it is a real image benchmark, then store only the last-minIterations # decode tasks. @@ -26,9 +26,9 @@ class ImageDecoding(multi_page_benchmark.MultiPageBenchmark): min_iterations = tab.runtime.Evaluate('minIterations') decode_image_events = decode_image_events[-min_iterations:] - durations = [d.duration_ms for d in decode_image_events] - if not durations: + elapsed_times = [d.elapsed_time for d in decode_image_events] + if not elapsed_times: results.Add('ImageDecoding_avg', 'ms', 'unsupported') return - image_decoding_avg = sum(durations) / len(durations) + image_decoding_avg = sum(elapsed_times) / len(elapsed_times) results.Add('ImageDecoding_avg', 'ms', image_decoding_avg) diff --git a/tools/telemetry/telemetry/inspector_timeline.py b/tools/telemetry/telemetry/inspector_timeline.py index 8faf38d..e0810c6 100644 --- a/tools/telemetry/telemetry/inspector_timeline.py +++ b/tools/telemetry/telemetry/inspector_timeline.py @@ -1,12 +1,51 @@ # Copyright (c) 2012 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -from telemetry.timeline_event import TimelineEvent -from telemetry.timeline_model import TimelineModel + class InspectorBackendException(Exception): pass + +class TimelineEvent(object): + """Represents a timeline event.""" + def __init__(self, d): + self.__dict__.update(d) + + @property + def type(self): + return self.__dict__.get('type') + + @property + def start_time(self): + return self.__dict__.get('startTime', 0) + + @property + def end_time(self): + return self.__dict__.get('endTime', 0) + + @property + def elapsed_time(self): + return self.end_time - self.start_time + + +class TimelineEvents(object): + def __init__(self): + self._events = [] + + def AppendRawEvents(self, raw_inspector_stream): + if raw_inspector_stream.get('params', {}).get('record'): + self._FlattenEvents(raw_inspector_stream['params']['record']) + + def _FlattenEvents(self, raw_inspector_events): + self._events.append(TimelineEvent(raw_inspector_events)) + for child in raw_inspector_events.get('children', []): + self._FlattenEvents(child) + + def GetAllOfType(self, type_name): + return [e for e in self._events if e.type == type_name] + + class InspectorTimeline(object): """Implementation of dev tools timeline.""" class Recorder(object): @@ -24,17 +63,17 @@ class InspectorTimeline(object): self._inspector_backend = inspector_backend self._tab = tab self._is_recording = False - self._timeline_model = None + self._timeline_events = None @property - def timeline_model(self): - return self._timeline_model + def timeline_events(self): + return self._timeline_events def Start(self): if self._is_recording: return + self._timeline_events = TimelineEvents() self._is_recording = True - self._timeline_model = TimelineModel() self._inspector_backend.RegisterDomain('Timeline', self._OnNotification, self._OnClose) req = {'method': 'Timeline.start'} @@ -44,7 +83,6 @@ class InspectorTimeline(object): if not self._is_recording: raise InspectorBackendException('Stop() called but not started') self._is_recording = False - self._timeline_model.DidFinishRecording() req = {'method': 'Timeline.stop'} self._SendSyncRequest(req) self._inspector_backend.UnregisterDomain('Timeline') @@ -59,63 +97,7 @@ class InspectorTimeline(object): if not self._is_recording: return if 'method' in msg and msg['method'] == 'Timeline.eventRecorded': - self._OnEventRecorded(msg) - - def _OnEventRecorded(self, msg): - record = msg.get('params', {}).get('record') - if record: - newly_created_event = InspectorTimeline.RawEventToTimelineEvent(record) - self._timeline_model.AddEvent(newly_created_event) - - @staticmethod - def RawEventToTimelineEvent(raw_inspector_event): - """Converts raw_inspector_event to TimelineEvent.""" - return InspectorTimeline._RawEventToTimelineEventRecursive( - None, raw_inspector_event) - - @staticmethod - def _RawEventToTimelineEventRecursive( - parent_for_created_events, raw_inspector_event): - """ - Creates a new TimelineEvent for the raw_inspector_event, if possible, adding - it to the provided parent_for_created_events. - - It then recurses on any child events found inside, building a tree of - TimelineEvents. - - Returns the root of the created tree, or None. - """ - # Create a TimelineEvent for this raw_inspector_event if possible. Only - # events with start-time and end-time get imported. - if ('startTime' in raw_inspector_event and - 'endTime' in raw_inspector_event): - args = {} - for x in raw_inspector_event: - if x in ('startTime', 'endTime', 'children'): - continue - args[x] = raw_inspector_event[x] - if len(args) == 0: - args = None - newly_created_event = TimelineEvent( - name=raw_inspector_event['type'], - start_time_ms=raw_inspector_event['startTime'], - duration_ms=(raw_inspector_event['endTime'] - - raw_inspector_event['startTime']), - args=args) - if parent_for_created_events: - parent_for_created_events.children.append(newly_created_event) - else: - newly_created_event = None - - # Process any children events, creating TimelineEvents for them as well. - if newly_created_event: - parent_for_children = newly_created_event - else: - parent_for_children = parent_for_created_events - for child in raw_inspector_event.get('children', []): - InspectorTimeline._RawEventToTimelineEventRecursive( - parent_for_children, child) - return newly_created_event + self._timeline_events.AppendRawEvents(msg) def _OnClose(self): if self._is_recording: diff --git a/tools/telemetry/telemetry/inspector_timeline_unittest.py b/tools/telemetry/telemetry/inspector_timeline_unittest.py index 6a7af8d..9e0ac7b 100644 --- a/tools/telemetry/telemetry/inspector_timeline_unittest.py +++ b/tools/telemetry/telemetry/inspector_timeline_unittest.py @@ -1,102 +1,63 @@ # Copyright (c) 2012 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. + import os import unittest +from telemetry import inspector_timeline from telemetry import tab_test_case from telemetry import util -from telemetry.inspector_timeline import InspectorTimeline - -_SAMPLE_MESSAGE = { - 'children': [ - {'data': {}, - 'startTime': 1352783525921.823, - 'type': 'BeginFrame', - 'usedHeapSize': 1870736}, - {'children': [], - 'data': {'height': 723, - 'width': 1272, - 'x': 0, - 'y': 0}, - 'endTime': 1352783525921.8992, - 'frameId': '10.2', - 'startTime': 1352783525921.8281, - 'type': 'Layout', - 'usedHeapSize': 1870736}, - {'children': [ - {'children': [], - 'data': {'imageType': 'PNG'}, - 'endTime': 1352783525927.7939, - 'startTime': 1352783525922.4241, - 'type': 'DecodeImage', - 'usedHeapSize': 1870736} - ], - 'data': {'height': 432, - 'width': 1272, - 'x': 0, - 'y': 8}, - 'endTime': 1352783525927.9822, - 'frameId': '10.2', - 'startTime': 1352783525921.9292, - 'type': 'Paint', - 'usedHeapSize': 1870736} - ], - 'data': {}, - 'endTime': 1352783525928.041, - 'startTime': 1352783525921.8049, - 'type': 'Program'} - -class InspectorEventParsingTest(unittest.TestCase): - def testParsingWithSampleData(self): - root_event = InspectorTimeline.RawEventToTimelineEvent(_SAMPLE_MESSAGE) - self.assertTrue(root_event) - decode_image_event = [ - child for child in root_event.GetAllChildrenRecursive() - if child.name == 'DecodeImage'][0] - self.assertEquals(decode_image_event.args['data']['imageType'], 'PNG') - self.assertTrue(decode_image_event.duration_ms > 0) - def testParsingWithSimpleData(self): - raw_event = {'type': 'Foo', - 'startTime': 1, - 'endTime': 3, - 'children': []} - event = InspectorTimeline.RawEventToTimelineEvent(raw_event) - self.assertEquals('Foo', event.name) - self.assertEquals(1, event.start_time_ms) - self.assertEquals(3, event.end_time_ms) - self.assertEquals(2, event.duration_ms) - self.assertEquals([], event.children) - def testParsingWithArgs(self): - raw_event = {'type': 'Foo', - 'startTime': 1, - 'endTime': 3, - 'foo': 7, - 'bar': {'x': 1}} - event = InspectorTimeline.RawEventToTimelineEvent(raw_event) - self.assertEquals('Foo', event.name) - self.assertEquals(1, event.start_time_ms) - self.assertEquals(3, event.end_time_ms) - self.assertEquals(2, event.duration_ms) - self.assertEquals([], event.children) - self.assertEquals(7, event.args['foo']) - self.assertEquals(1, event.args['bar']['x']) +_SAMPLE_STREAM = [ +{u'method': u'Timeline.eventRecorded', + u'params': {u'record': {u'children': [ + {u'data': {}, + u'startTime': 1352783525921.823, + u'type': u'BeginFrame', + u'usedHeapSize': 1870736}, + {u'children': [], + u'data': {u'height': 723, + u'width': 1272, + u'x': 0, + u'y': 0}, + u'endTime': 1352783525921.8992, + u'frameId': u'10.2', + u'startTime': 1352783525921.8281, + u'type': u'Layout', + u'usedHeapSize': 1870736}, + {u'children': [{u'children': [], + u'data': {u'imageType': u'PNG'}, + u'endTime': 1352783525927.7939, + u'startTime': 1352783525922.4241, + u'type': u'DecodeImage', + u'usedHeapSize': 1870736}], + u'data': {u'height': 432, + u'width': 1272, + u'x': 0, + u'y': 8}, + u'endTime': 1352783525927.9822, + u'frameId': u'10.2', + u'startTime': 1352783525921.9292, + u'type': u'Paint', + u'usedHeapSize': 1870736}], +u'data': {}, +u'endTime': 1352783525928.041, +u'startTime': 1352783525921.8049, +u'type': u'Program'}}}, +] - def testEventsWithNoStartTimeAreDropped(self): - raw_event = {'type': 'Foo', - 'endTime': 1, - 'children': []} - event = InspectorTimeline.RawEventToTimelineEvent(raw_event) - self.assertEquals(None, event) - def testEventsWithNoEndTimeAreDropped(self): - raw_event = {'type': 'Foo', - 'endTime': 1, - 'children': []} - event = InspectorTimeline.RawEventToTimelineEvent(raw_event) - self.assertEquals(None, event) +class InspectorTimelineTest(unittest.TestCase): + def testTimelineEventParsing(self): + timeline_events = inspector_timeline.TimelineEvents() + for raw_events in _SAMPLE_STREAM: + timeline_events.AppendRawEvents(raw_events) + decode_image_events = timeline_events.GetAllOfType('DecodeImage') + self.assertEquals(len(decode_image_events), 1) + self.assertEquals(decode_image_events[0].data['imageType'], 'PNG') + self.assertTrue(decode_image_events[0].elapsed_time > 0) class InspectorTimelineTabTest(tab_test_case.TabTestCase): @@ -114,7 +75,7 @@ class InspectorTimelineTabTest(tab_test_case.TabTestCase): def testGotTimeline(self): self._StartServer() image_url = self._browser.http_server.UrlOf('image.png') - with InspectorTimeline.Recorder(self._tab.timeline): + with inspector_timeline.InspectorTimeline.Recorder(self._tab.timeline): self._tab.runtime.Execute( """ var done = false; @@ -125,7 +86,7 @@ window.webkitRequestAnimationFrame(function() { done = true; }); """ % image_url) self._WaitForAnimationFrame() - r = self._tab.timeline.timeline_model.GetAllOfName('DecodeImage') + r = self._tab.timeline.timeline_events.GetAllOfType('DecodeImage') self.assertTrue(len(r) > 0) - self.assertEquals(r[0].args['data']['imageType'], 'PNG') - self.assertTrue(r[0].duration_ms > 0) + self.assertEquals(r[0].data['imageType'], 'PNG') + self.assertTrue(r[0].elapsed_time > 0) diff --git a/tools/telemetry/telemetry/timeline_event.py b/tools/telemetry/telemetry/timeline_event.py deleted file mode 100644 index bbcafb2..0000000 --- a/tools/telemetry/telemetry/timeline_event.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -class TimelineEvent(object): - """Represents a timeline event.""" - def __init__(self, name, start_time_ms, duration_ms, args=None): - self.name = name - self.start_time_ms = start_time_ms - self.duration_ms = duration_ms - self.children = [] - self.args = args - - @property - def end_time_ms(self): - return self.start_time_ms + self.duration_ms - - @property - def self_time_ms(self): - """Time spent in this function less any time spent in child events.""" - child_total = sum( - [e.duration_ms for e in self.children]) - return self.duration_ms - child_total - - def __repr__(self): - if self.args: - args_str = ', ' + repr(self.args) - else: - args_str = '' - - return "TimelineEvent(name='%s', start_ms=%f, duration_ms=%s%s)" % ( - self.name, - self.start_time_ms, - self.duration_ms, - args_str) - - @staticmethod - def _GetAllChildrenRecursive(events, item): - events.append(item) - for child in item.children: - TimelineEvent._GetAllChildrenRecursive(events, child) - - def GetAllChildrenRecursive(self, include_self=False): - events = [] - TimelineEvent._GetAllChildrenRecursive(events, self) - if not include_self: - del events[0] - return events diff --git a/tools/telemetry/telemetry/timeline_event_unittest.py b/tools/telemetry/telemetry/timeline_event_unittest.py deleted file mode 100644 index 94d59c1..0000000 --- a/tools/telemetry/telemetry/timeline_event_unittest.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import unittest - -from telemetry.timeline_event import TimelineEvent - -class TimelineEventTest(unittest.TestCase): - def testChildrenLogic(self): - # [ top ] - # [ a ] [ b ] - # [x] - top = TimelineEvent('top', 0, 10) - a = TimelineEvent('a', 1, 2) - x = TimelineEvent('x', 1.5, 0.25) - b = TimelineEvent('b', 5, 2) - top.children.extend([a, b]) - a.children.append(x) - - all_children = top.GetAllChildrenRecursive(include_self=True) - self.assertEquals([top, a, x, b], all_children) - - self.assertEquals(x.self_time_ms, 0.25) - self.assertEquals(a.self_time_ms, 1.75) # 2 - 0.25 - self.assertEquals(top.self_time_ms, 6) # 10 - 2 -2 - diff --git a/tools/telemetry/telemetry/timeline_model.py b/tools/telemetry/telemetry/timeline_model.py deleted file mode 100644 index fe19a91..0000000 --- a/tools/telemetry/telemetry/timeline_model.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -class TimelineModel(object): - def __init__(self): - self._events = [] - self._frozen = False - - def AddEvent(self, event): - if self._frozen: - raise Exception("Cannot add events once recording is done") - self._events.extend( - event.GetAllChildrenRecursive(include_self=True)) - - def DidFinishRecording(self): - self._frozen = True - - def GetAllEvents(self): - return self._events - - def GetAllOfName(self, name): - return [e for e in self._events if e.name == name] diff --git a/tools/telemetry/telemetry/timeline_model_unittest.py b/tools/telemetry/telemetry/timeline_model_unittest.py deleted file mode 100644 index 1adf9d9..0000000 --- a/tools/telemetry/telemetry/timeline_model_unittest.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import unittest - -from telemetry.timeline_event import TimelineEvent -from telemetry.timeline_model import TimelineModel - -class TimelineModelUnittest(unittest.TestCase): - def testTimelineEventsOfType(self): - timeline_model = TimelineModel() - a = TimelineEvent('a', 0, 10) - b = TimelineEvent('b', 11, 10) - timeline_model.AddEvent(a) - timeline_model.AddEvent(b) - timeline_model.DidFinishRecording() - self.assertEquals(1, len(timeline_model.GetAllOfName('a'))) |