| Index: tools/telemetry/telemetry/web_perf/metrics/mainthread_jank_unittest.py
|
| diff --git a/tools/telemetry/telemetry/web_perf/metrics/mainthread_jank_unittest.py b/tools/telemetry/telemetry/web_perf/metrics/mainthread_jank_unittest.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c18d671299b04aad1ce90fb94c2f087507d72f5c
|
| --- /dev/null
|
| +++ b/tools/telemetry/telemetry/web_perf/metrics/mainthread_jank_unittest.py
|
| @@ -0,0 +1,113 @@
|
| +# Copyright 2014 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.web_perf import timeline_interaction_record as tir_module
|
| +from telemetry.web_perf.metrics import mainthread_jank
|
| +from telemetry.web_perf.metrics import unittest_util
|
| +from telemetry.core.timeline import model as model_module
|
| +
|
| +
|
| +class MainthreadJankTests(unittest.TestCase):
|
| +
|
| + def testComputeMainThreadJankStats(self):
|
| + # The slice hierarchy should look something like this:
|
| + # [ MessageLoop::RunTask ] [MessageLoop::RunTask][ MessagLoop::RunTask ]
|
| + # [ foo ] [ bar ]
|
| + # | |
|
| + # 200ms 800ms
|
| + # (thread_start) (thread_end)
|
| + #
|
| + # Note: all timings mentioned here and in comments below are thread time.
|
| +
|
| + model = model_module.TimelineModel()
|
| + renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
|
| + renderer_main.name = 'CrRendererMain'
|
| +
|
| + # [ MessageLoop::RunTask ]
|
| + # 100ms 300ms
|
| + renderer_main.BeginSlice('toplevel', 'MessageLoop::RunTask', 112, 100)
|
| + renderer_main.EndSlice(240, 300)
|
| +
|
| + # [ MessageLoop::RunTask ]
|
| + # 450ms [ foo ] 475 ms
|
| + # 460ms 470ms
|
| + renderer_main.BeginSlice('toplevel', 'MessageLoop::RunTask', 462, 450)
|
| + renderer_main.BeginSlice('otherlevel', 'foo', 468, 460)
|
| + renderer_main.EndSlice(475, 470)
|
| + renderer_main.EndSlice(620, 475)
|
| +
|
| + # [ MessageLoop::RunTask ]
|
| + # 620ms [ bar ] 900ms
|
| + # 750ms 850ms
|
| + renderer_main.BeginSlice('toplevel', 'MessageLoop::RunTask', 652, 620)
|
| + renderer_main.BeginSlice('otherlevel', 'bar', 785, 750)
|
| + renderer_main.EndSlice(875, 850)
|
| + renderer_main.EndSlice(1040, 900)
|
| +
|
| + model.FinalizeImport(shift_world_to_zero=False)
|
| +
|
| + stat = mainthread_jank._ComputeMainThreadJankStats( # pylint: disable=W0212
|
| + renderer_main, thread_start=200, thread_end=800)
|
| +
|
| + # The overlapped between thread time range(200ms -> 800ms)
|
| + # with the first top slice (100ms -> 300ms) is 300 - 200 = 100ms,
|
| + # with the second slice (450ms -> 475ms) is 475 - 450 = 25 ms,
|
| + # with the third slice (620ms -> 900ms) is 800 - 620 = 180 ms.
|
| + #
|
| + # Hence we have 2 big top slices which overlapped duration > 50ms,
|
| + # the biggest top slice is 180ms, the total top slices's thread time is
|
| + # 100 + 25 + 180 = 305ms, and the total big top slice's thread time is
|
| + # 100 + 180 = 280ms.
|
| + self.assertEquals(2, stat.num_big_top_slices)
|
| + self.assertEquals(180, stat.biggest_top_slice_thread_time)
|
| + self.assertEquals(305, stat.sum_top_slices_thread_time)
|
| + self.assertEquals(280, stat.sum_big_top_slices_thread_time)
|
| +
|
| + def testMainthreadJankAddResults(self):
|
| + # [ MessageLoop::RunTask] [MessageLoop::RunTask] [MessagLoop::RunTask]
|
| + # 10 100 120 400 450 750
|
| + # [ record_1 ] [ record_2 ] [ record_3 ]
|
| + # 40 70 120 200 220 900
|
| + test_records = [
|
| + tir_module.TimelineInteractionRecord('test1', 10, 80, 40, 70),
|
| + tir_module.TimelineInteractionRecord('test1', 130, 210, 120, 200),
|
| + tir_module.TimelineInteractionRecord('test1', 250, 820, 220, 900)
|
| + ]
|
| +
|
| + model = model_module.TimelineModel()
|
| + renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
|
| + renderer_main.name = 'CrRendererMain'
|
| +
|
| + # [ MessageLoop::RunTask ]
|
| + # 10ms 100ms
|
| + renderer_main.BeginSlice('toplevel', 'MessageLoop::RunTask', 12, 10)
|
| + renderer_main.EndSlice(120, 100)
|
| +
|
| + # [ MessageLoop::RunTask ]
|
| + # 120ms 200ms
|
| + renderer_main.BeginSlice('toplevel', 'MessageLoop::RunTask', 125, 120)
|
| + renderer_main.EndSlice(210, 400)
|
| +
|
| + # [ MessageLoop::RunTask ]
|
| + # 220ms 900ms
|
| + renderer_main.BeginSlice('toplevel', 'MessageLoop::RunTask', 477, 450)
|
| + renderer_main.EndSlice(772, 750)
|
| +
|
| + model.FinalizeImport(shift_world_to_zero=False)
|
| +
|
| + results = unittest_util.FakeResults()
|
| + metric = mainthread_jank.MainthreadJankMetric()
|
| + metric.AddResults(model, renderer_main, test_records, results)
|
| + # Main thread janks covered by records' ranges are:
|
| + # Record 1: (40ms -> 70ms)
|
| + # Record 2: (120ms -> 200ms)
|
| + # Record 3: (220ms -> 400ms), (450ms -> 750ms)
|
| + self.assertEquals(3, results.GetResult('num_big_janks').value)
|
| + self.assertEquals(590, results.GetResult('total_jank_thread_time').value)
|
| + self.assertEquals(560,
|
| + results.GetResult('total_big_jank_thread_time').value)
|
| + self.assertEquals(300, results.GetResult('biggest_jank_thread_time').value)
|
| +
|
|
|