def GetAdjustedInteractionIfContainGesture(timeline, interaction_record): """ Returns a new interaction record if interaction_record contains geture whose time range that overlaps with interaction_record's range. If not, returns a clone of original interaction_record. The synthetic gesture controller inserts a trace marker to precisely demarcate when the gesture was running. We check for overlap, not inclusion, because gesture_actions can start/end slightly outside the telemetry markers on Windows. This problem is probably caused by a race condition between the browser and renderer process submitting the trace events for the markers. """ # Only adjust the range for gestures. if not interaction_record.label.startswith('Gesture_'): return copy.copy(interaction_record) gesture_events = [ ev for ev in timeline.IterAllAsyncSlicesOfName( 'SyntheticGestureController::running') if ev.parent_slice is None and ev.start <= interaction_record.end and ev.end >= interaction_record.start ] if len(gesture_events) == 0: return copy.copy(interaction_record) if len(gesture_events) > 1: raise Exception( 'More than one possible synthetic gesture marker found in ' 'interaction_record %s.' % interaction_record.label) return tir_module.TimelineInteractionRecord(interaction_record.label, gesture_events[0].start, gesture_events[0].end, gesture_events[0], interaction_record._flags) # pylint: disable=protected-access
def testDisplayStats(self): timeline = model.TimelineModel() timer = MockTimer() ref_stats = ReferenceRenderingStats() ref_stats.AppendNewRange() renderer = timeline.GetOrCreateProcess(pid=2) browser = timeline.GetOrCreateProcess(pid=3) browser_main = browser.GetOrCreateThread(tid=31) browser_main.BeginSlice('webkit.console', 'ActionA', timer.AdvanceAndGet(2, 4), '') # Create display rendering stats. for i in xrange(0, 10): first = (i == 0) AddDisplayRenderingStats(timer, browser_main, first, ref_stats) timer.Advance(5, 10) browser_main.EndSlice(timer.AdvanceAndGet()) timer.Advance(2, 4) browser.FinalizeImport() timeline_markers = timeline.FindTimelineMarkers(['ActionA']) records = [ tir_module.TimelineInteractionRecord(e.name, e.start, e.end) for e in timeline_markers ] stats = rendering_stats.RenderingStats(renderer, browser, None, records) # Compare rendering stats to reference - Only display stats should count self.assertEquals(stats.frame_timestamps, ref_stats.frame_timestamps) self.assertEquals(stats.frame_times, ref_stats.frame_times)
def testRangeWithoutFrames(self): timer = MockTimer() timeline = model.TimelineModel() # Create a renderer process, with a main thread and impl thread. renderer = timeline.GetOrCreateProcess(pid=2) renderer_main = renderer.GetOrCreateThread(tid=21) renderer_main.BeginSlice('webkit.console', 'ActionA', timer.AdvanceAndGet(2, 4), '') renderer_main.EndSlice(timer.AdvanceAndGet(2, 4)) timer.Advance(2, 4) # Create Action B without any frames. This should trigger # NotEnoughFramesError when the RenderingStats object is created. renderer_main.BeginSlice('webkit.console', 'ActionB', timer.AdvanceAndGet(2, 4), '') renderer_main.EndSlice(timer.AdvanceAndGet(2, 4)) renderer.FinalizeImport() timeline_markers = timeline.FindTimelineMarkers(['ActionA', 'ActionB']) records = [ tir_module.TimelineInteractionRecord(e.name, e.start, e.end) for e in timeline_markers ] stats = rendering_stats.RenderingStats(renderer, None, None, records) self.assertEquals(0, len(stats.frame_timestamps[1]))
def testBothSurfaceFlingerAndDisplayStats(self): timeline = model.TimelineModel() timer = MockTimer() ref_stats = ReferenceRenderingStats() ref_stats.AppendNewRange() surface_flinger = timeline.GetOrCreateProcess(pid=4) surface_flinger.name = 'SurfaceFlinger' surface_flinger_thread = surface_flinger.GetOrCreateThread(tid=41) renderer = timeline.GetOrCreateProcess(pid=2) browser = timeline.GetOrCreateProcess(pid=3) browser_main = browser.GetOrCreateThread(tid=31) browser_main.BeginSlice('webkit.console', 'ActionA', timer.AdvanceAndGet(2, 4), '') # Create SurfaceFlinger stats and display rendering stats. for i in xrange(0, 10): first = (i == 0) AddSurfaceFlingerStats(timer, surface_flinger_thread, first, ref_stats) timer.Advance(2, 4) for i in xrange(0, 10): first = (i == 0) AddDisplayRenderingStats(timer, browser_main, first, None) timer.Advance(5, 10) browser_main.EndSlice(timer.AdvanceAndGet()) timer.Advance(2, 4) browser.FinalizeImport() renderer.FinalizeImport() timeline_markers = timeline.FindTimelineMarkers(['ActionA']) records = [ tir_module.TimelineInteractionRecord(e.name, e.start, e.end) for e in timeline_markers ] metadata = [{ 'name': 'metadata', 'value': { 'surface_flinger': { 'refresh_period': 16.6666 } } }] stats = rendering_stats.RenderingStats(renderer, browser, surface_flinger, None, records, metadata) # Compare rendering stats to reference - Only SurfaceFlinger stats should # count self.assertEquals(stats.frame_timestamps, ref_stats.frame_timestamps) self.assertEquals(stats.frame_times, ref_stats.frame_times)
def testBothDrmAndDisplayStats(self): timeline = model.TimelineModel() timer = MockTimer() vblank_timer = MockVblankTimer() ref_stats = ReferenceRenderingStats() ref_stats.AppendNewRange() gpu = timeline.GetOrCreateProcess(pid=6) gpu.name = 'GPU Process' gpu_drm_thread = gpu.GetOrCreateThread(tid=61) renderer = timeline.GetOrCreateProcess(pid=2) browser = timeline.GetOrCreateProcess(pid=3) browser_main = browser.GetOrCreateThread(tid=31) browser_main.BeginSlice('webkit.console', 'ActionA', timer.AdvanceAndGet(2, 4), '') vblank_timer.TvAdvance(2000, 4000) # Create drm flip stats and display rendering stats. for i in xrange(0, 10): first = (i == 0) AddDrmEventFlipStats(timer, vblank_timer, gpu_drm_thread, first, ref_stats) timer.Advance(2, 4) vblank_timer.TvAdvance(2000, 4000) for i in xrange(0, 10): first = (i == 0) AddDisplayRenderingStats(timer, browser_main, first, None) timer.Advance(5, 10) vblank_timer.TvAdvance(5000, 10000) browser_main.EndSlice(timer.AdvanceAndGet()) timer.Advance(2, 4) vblank_timer.TvAdvance(2000, 4000) browser.FinalizeImport() renderer.FinalizeImport() timeline_markers = timeline.FindTimelineMarkers(['ActionA']) records = [ tir_module.TimelineInteractionRecord(e.name, e.start, e.end) for e in timeline_markers ] stats = rendering_stats.RenderingStats(renderer, browser, None, gpu, records) # Compare rendering stats to reference - Only drm flip stats should # count self.assertEquals(stats.frame_timestamps, ref_stats.frame_timestamps) self.assertEquals(stats.frame_times, ref_stats.frame_times)
def MeasurePage(self, page, tab, results): # In current telemetry tests, all tests wait for DocumentComplete state, # but we need to wait for the load event. tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300) # TODO(nduca): when crbug.com/168431 is fixed, modify the page sets to # recognize loading as a toplevel action. self._timeline_controller.Stop(tab) loading.LoadingMetric().AddResults(tab, results) timeline_metric = timeline.LoadTimesTimelineMetric() renderer_thread = \ self._timeline_controller.model.GetRendererThreadFromTab(tab) record = tir_module.TimelineInteractionRecord( "loading_trace_interaction", 0, float('inf')) timeline_metric.AddResults(self._timeline_controller.model, renderer_thread, [record], results)
def testFromTimeline(self): timeline = model.TimelineModel() # Create a browser process and a renderer process, and a main thread and # impl thread for each. browser = timeline.GetOrCreateProcess(pid=1) browser_main = browser.GetOrCreateThread(tid=11) renderer = timeline.GetOrCreateProcess(pid=2) timer = MockTimer() browser_ref_stats = ReferenceRenderingStats() browser_ref_stats.AppendNewRange() # Add display rendering stats. browser_main.BeginSlice('webkit.console', 'Action0', timer.AdvanceAndGet(2, 4), '') for i in xrange(0, 10): first = (i == 0) AddDisplayRenderingStats(timer, browser_main, first, browser_ref_stats) timer.Advance(5, 10) browser_main.EndSlice(timer.AdvanceAndGet(2, 4)) browser.FinalizeImport() timeline_markers = timeline.FindTimelineMarkers(['Action0']) records = [ tir_module.TimelineInteractionRecord(e.name, e.start, e.end) for e in timeline_markers ] stats = rendering_stats.RenderingStats(renderer, browser, None, records) # Compare rendering stats to reference. self.assertEquals(stats.frame_timestamps, browser_ref_stats.frame_timestamps) self.assertEquals(stats.frame_times, browser_ref_stats.frame_times)
def TestInteraction(start, end): return timeline_interaction_record.TimelineInteractionRecord( 'Action_TestInteraction', start, end)
def _GetInteractionRecord(start, end): return tir_module.TimelineInteractionRecord("test-record", start, end)
def testGetAdjustedInteractionIfContainGesture(self): model = model_module.TimelineModel() renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2) renderer_main.name = 'CrRendererMain' # [ X ] [ Y ] # [ sub_async_slice_X ] # [ record_1] # [ record_6] # [ record_2 ] [ record_3 ] # [ record_4 ] # [ record_5 ] # # Note: X and Y are async slice with name # SyntheticGestureController::running async_slice_X = async_slice.AsyncSlice( 'X', 'SyntheticGestureController::running', 10, duration=20, start_thread=renderer_main, end_thread=renderer_main) sub_async_slice_X = async_slice.AsyncSlice( 'X', 'SyntheticGestureController::running', 10, duration=20, start_thread=renderer_main, end_thread=renderer_main) sub_async_slice_X.parent_slice = async_slice_X async_slice_X.AddSubSlice(sub_async_slice_X) async_slice_Y = async_slice.AsyncSlice( 'X', 'SyntheticGestureController::running', 60, duration=20, start_thread=renderer_main, end_thread=renderer_main) renderer_main.AddAsyncSlice(async_slice_X) renderer_main.AddAsyncSlice(async_slice_Y) model.FinalizeImport(shift_world_to_zero=False) record_1 = tir_module.TimelineInteractionRecord( 'Gesture_included', 15, 25) record_2 = tir_module.TimelineInteractionRecord( 'Gesture_overlapped_left', 5, 25) record_3 = tir_module.TimelineInteractionRecord( 'Gesture_overlapped_right', 25, 35) record_4 = tir_module.TimelineInteractionRecord( 'Gesture_containing', 5, 35) record_5 = tir_module.TimelineInteractionRecord( 'Gesture_non_overlapped', 35, 45) record_6 = tir_module.TimelineInteractionRecord( 'Action_included', 15, 25) adjusted_record_1 = sg_util.GetAdjustedInteractionIfContainGesture( model, record_1) self.assertEquals(adjusted_record_1.start, 10) self.assertEquals(adjusted_record_1.end, 30) self.assertTrue(adjusted_record_1 is not record_1) adjusted_record_2 = sg_util.GetAdjustedInteractionIfContainGesture( model, record_2) self.assertEquals(adjusted_record_2.start, 10) self.assertEquals(adjusted_record_2.end, 30) adjusted_record_3 = sg_util.GetAdjustedInteractionIfContainGesture( model, record_3) self.assertEquals(adjusted_record_3.start, 10) self.assertEquals(adjusted_record_3.end, 30) adjusted_record_4 = sg_util.GetAdjustedInteractionIfContainGesture( model, record_4) self.assertEquals(adjusted_record_4.start, 10) self.assertEquals(adjusted_record_4.end, 30) adjusted_record_5 = sg_util.GetAdjustedInteractionIfContainGesture( model, record_5) self.assertEquals(adjusted_record_5.start, 35) self.assertEquals(adjusted_record_5.end, 45) self.assertTrue(adjusted_record_5 is not record_5) adjusted_record_6 = sg_util.GetAdjustedInteractionIfContainGesture( model, record_6) self.assertEquals(adjusted_record_6.start, 15) self.assertEquals(adjusted_record_6.end, 25) self.assertTrue(adjusted_record_6 is not record_6)
from telemetry.timeline import async_slice as async_slice_module from telemetry.timeline import model as model_module from telemetry.timeline import slice as slice_module from telemetry.unittest_util import test_page_test_results from telemetry.web_perf.metrics import gpu_timeline from telemetry.web_perf import timeline_interaction_record as tir_module SERVICE_FRAME_END_CATEGORY, SERVICE_FRAME_END_NAME = \ gpu_timeline.SERVICE_FRAME_END_MARKER DEVICE_FRAME_END_CATEGORY, DEVICE_FRAME_END_NAME = \ gpu_timeline.DEVICE_FRAME_END_MARKER INTERACTION_RECORDS = [ tir_module.TimelineInteractionRecord("test-record", 0, float('inf')) ] def _CreateGPUSlices(parent_thread, name, start_time, duration, offset=0): args = {'gl_category': gpu_timeline.TOPLEVEL_GL_CATEGORY} return (slice_module.Slice(parent_thread, gpu_timeline.TOPLEVEL_SERVICE_CATEGORY, name, start_time, args=args, duration=duration, thread_duration=duration), async_slice_module.AsyncSlice( gpu_timeline.TOPLEVEL_DEVICE_CATEGORY, name,
def testInputLatencyFromTimeline(self): timeline = model.TimelineModel() # Create a browser process and a renderer process. browser = timeline.GetOrCreateProcess(pid=1) browser_main = browser.GetOrCreateThread(tid=11) renderer = timeline.GetOrCreateProcess(pid=2) renderer_main = renderer.GetOrCreateThread(tid=21) timer = MockTimer() ref_latency = ReferenceInputLatencyStats() # Create 10 input latency stats events for Action A. renderer_main.BeginSlice('webkit.console', 'ActionA', timer.AdvanceAndGet(2, 4), '') for _ in xrange(0, 10): AddInputLatencyStats(timer, browser_main, renderer_main, ref_latency) renderer_main.EndSlice(timer.AdvanceAndGet(2, 4)) # Create 5 input latency stats events not within any action. timer.Advance(2, 4) for _ in xrange(0, 5): AddInputLatencyStats(timer, browser_main, renderer_main, None) # Create 10 input latency stats events for Action B. renderer_main.BeginSlice('webkit.console', 'ActionB', timer.AdvanceAndGet(2, 4), '') for _ in xrange(0, 10): AddInputLatencyStats(timer, browser_main, renderer_main, ref_latency) renderer_main.EndSlice(timer.AdvanceAndGet(2, 4)) # Create 10 input latency stats events for Action A. renderer_main.BeginSlice('webkit.console', 'ActionA', timer.AdvanceAndGet(2, 4), '') for _ in xrange(0, 10): AddInputLatencyStats(timer, browser_main, renderer_main, ref_latency) renderer_main.EndSlice(timer.AdvanceAndGet(2, 4)) browser.FinalizeImport() renderer.FinalizeImport() latency_events = [] timeline_markers = timeline.FindTimelineMarkers( ['ActionA', 'ActionB', 'ActionA']) records = [ tir_module.TimelineInteractionRecord(e.name, e.start, e.end) for e in timeline_markers ] for record in records: if record.GetBounds().is_empty: continue latency_events.extend( rendering_stats.GetLatencyEvents(browser, record.GetBounds())) self.assertEquals(latency_events, ref_latency.input_event) event_latency_result = rendering_stats.ComputeEventLatencies( latency_events) self.assertEquals(event_latency_result, ref_latency.input_event_latency) stats = rendering_stats.RenderingStats(renderer, browser, None, records) self.assertEquals( perf_tests_helper.FlattenList(stats.input_event_latency), [ latency for name, latency in ref_latency.input_event_latency if name != rendering_stats.MAIN_THREAD_SCROLL_UPDATE_EVENT_NAME ]) self.assertEquals( perf_tests_helper.FlattenList(stats.main_thread_scroll_latency), [ latency for name, latency in ref_latency.input_event_latency if name == rendering_stats.MAIN_THREAD_SCROLL_UPDATE_EVENT_NAME ]) self.assertEquals( perf_tests_helper.FlattenList(stats.gesture_scroll_update_latency), [ latency for name, latency in ref_latency.input_event_latency if name == rendering_stats.GESTURE_SCROLL_UPDATE_EVENT_NAME ])
from telemetry.testing import test_page_test_results from telemetry.timeline import async_slice as async_slice_module from telemetry.timeline import domain.model as model_module from telemetry.timeline import slice as slice_module from telemetry.web_perf.metrics import gpu_timeline from telemetry.web_perf import timeline_interaction_record as tir_module SERVICE_FRAME_END_CATEGORY, SERVICE_FRAME_END_NAME = \ gpu_timeline.SERVICE_FRAME_END_MARKER DEVICE_FRAME_END_CATEGORY, DEVICE_FRAME_END_NAME = \ gpu_timeline.DEVICE_FRAME_END_MARKER INTERACTION_RECORDS = [tir_module.TimelineInteractionRecord("test-record", 0, float('inf'))] def _CreateGPUSlices(parent_thread, name, start_time, duration, offset=0): args = {'gl_category': gpu_timeline.TOPLEVEL_GL_CATEGORY} return (slice_module.Slice(parent_thread, gpu_timeline.TOPLEVEL_SERVICE_CATEGORY, name, start_time, args=args, duration=duration, thread_duration=duration), async_slice_module.AsyncSlice(gpu_timeline.TOPLEVEL_DEVICE_CATEGORY, name, start_time + offset, args=args, duration=duration))
def testFromTimeline(self): timeline = model.TimelineModel() # Create a browser process and a renderer process, and a main thread and # impl thread for each. browser = timeline.GetOrCreateProcess(pid=1) browser_main = browser.GetOrCreateThread(tid=11) browser_compositor = browser.GetOrCreateThread(tid=12) renderer = timeline.GetOrCreateProcess(pid=2) renderer_main = renderer.GetOrCreateThread(tid=21) renderer_compositor = renderer.GetOrCreateThread(tid=22) timer = MockTimer() renderer_ref_stats = ReferenceRenderingStats() browser_ref_stats = ReferenceRenderingStats() browser_ref_stats.AppendNewRange() renderer_ref_stats.AppendNewRange() # Add display rendering stats. browser_main.BeginSlice('webkit.console', 'Action0', timer.AdvanceAndGet(2, 4), '') for i in xrange(0, 10): first = (i == 0) AddDisplayRenderingStats(timer, browser_main, first, browser_ref_stats) timer.Advance(5, 10) browser_main.EndSlice(timer.AdvanceAndGet(2, 4)) # Create 10 main and impl rendering stats events for Action A. renderer_main.BeginSlice('webkit.console', 'ActionA', timer.AdvanceAndGet(2, 4), '') renderer_ref_stats.AppendNewRange() browser_ref_stats.AppendNewRange() for i in xrange(0, 10): first = (i == 0) AddImplThreadRenderingStats(timer, renderer_compositor, first, renderer_ref_stats) AddImplThreadRenderingStats(timer, browser_compositor, first, None) renderer_main.EndSlice(timer.AdvanceAndGet(2, 4)) # Create 5 main and impl rendering stats events not within any action. for i in xrange(0, 5): first = (i == 0) AddImplThreadRenderingStats(timer, renderer_compositor, first, None) AddImplThreadRenderingStats(timer, browser_compositor, first, None) # Create 10 main and impl rendering stats events for Action B. renderer_main.BeginSlice('webkit.console', 'ActionB', timer.AdvanceAndGet(2, 4), '') renderer_ref_stats.AppendNewRange() browser_ref_stats.AppendNewRange() for i in xrange(0, 10): first = (i == 0) AddImplThreadRenderingStats(timer, renderer_compositor, first, renderer_ref_stats) AddImplThreadRenderingStats(timer, browser_compositor, first, None) renderer_main.EndSlice(timer.AdvanceAndGet(2, 4)) # Create 10 main and impl rendering stats events for Action A. renderer_main.BeginSlice('webkit.console', 'ActionA', timer.AdvanceAndGet(2, 4), '') renderer_ref_stats.AppendNewRange() browser_ref_stats.AppendNewRange() for i in xrange(0, 10): first = (i == 0) AddImplThreadRenderingStats(timer, renderer_compositor, first, renderer_ref_stats) AddImplThreadRenderingStats(timer, browser_compositor, first, None) renderer_main.EndSlice(timer.AdvanceAndGet(2, 4)) timer.Advance(2, 4) browser.FinalizeImport() renderer.FinalizeImport() timeline_markers = timeline.FindTimelineMarkers( ['Action0', 'ActionA', 'ActionB', 'ActionA']) records = [ tir_module.TimelineInteractionRecord(e.name, e.start, e.end) for e in timeline_markers ] stats = rendering_stats.RenderingStats(renderer, browser, None, None, records) # Compare rendering stats to reference. self.assertEquals(stats.frame_timestamps, browser_ref_stats.frame_timestamps) self.assertEquals(stats.frame_times, browser_ref_stats.frame_times) self.assertEquals(stats.approximated_pixel_percentages, renderer_ref_stats.approximated_pixel_percentages) self.assertEquals(stats.checkerboarded_pixel_percentages, renderer_ref_stats.checkerboarded_pixel_percentages)
def testGetAdjustedInteractionIfContainGesture(self): model = model_module.TimelineModel() renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2) renderer_main.name = 'CrRendererMain' # [ X ] [ Y ] # [ record_1] # [ record_6] # [ record_2 ] [ record_3 ] # [ record_4 ] # [ record_5 ] renderer_main.BeginSlice('X', 'SyntheticGestureController::running', 10, 0) renderer_main.EndSlice(30, 30) renderer_main.BeginSlice('Y', 'SyntheticGestureController::running', 60, 0) renderer_main.EndSlice(80, 80) model.FinalizeImport(shift_world_to_zero=False) record_1 = tir_module.TimelineInteractionRecord( 'Gesture_included', 15, 25) record_2 = tir_module.TimelineInteractionRecord( 'Gesture_overlapped_left', 5, 25) record_3 = tir_module.TimelineInteractionRecord( 'Gesture_overlapped_right', 25, 35) record_4 = tir_module.TimelineInteractionRecord( 'Gesture_containing', 5, 35) record_5 = tir_module.TimelineInteractionRecord( 'Gesture_non_overlapped', 35, 45) record_6 = tir_module.TimelineInteractionRecord( 'Action_included', 15, 25) adjusted_record_1 = sg_util.GetAdjustedInteractionIfContainGesture( model, record_1) self.assertEquals(adjusted_record_1.start, 10) self.assertEquals(adjusted_record_1.end, 30) self.assertTrue(adjusted_record_1 is not record_1) adjusted_record_2 = sg_util.GetAdjustedInteractionIfContainGesture( model, record_2) self.assertEquals(adjusted_record_2.start, 10) self.assertEquals(adjusted_record_2.end, 30) adjusted_record_3 = sg_util.GetAdjustedInteractionIfContainGesture( model, record_3) self.assertEquals(adjusted_record_3.start, 10) self.assertEquals(adjusted_record_3.end, 30) adjusted_record_4 = sg_util.GetAdjustedInteractionIfContainGesture( model, record_4) self.assertEquals(adjusted_record_4.start, 10) self.assertEquals(adjusted_record_4.end, 30) adjusted_record_5 = sg_util.GetAdjustedInteractionIfContainGesture( model, record_5) self.assertEquals(adjusted_record_5.start, 35) self.assertEquals(adjusted_record_5.end, 45) self.assertTrue(adjusted_record_5 is not record_5) adjusted_record_6 = sg_util.GetAdjustedInteractionIfContainGesture( model, record_6) self.assertEquals(adjusted_record_6.start, 15) self.assertEquals(adjusted_record_6.end, 25) self.assertTrue(adjusted_record_6 is not record_6)
def AddInteractionRecord(self, label, start, end): self._interaction_records.append( timeline_interaction_record.TimelineInteractionRecord(label, start, end))