1# Copyright 2014 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5 6# A top level slice of a main thread can cause the webapp to behave 7# unresponsively if its thread duration is greater than or equals to 8# USER_PERCEIVABLE_DELAY_THRESHOLD_MS. Human eyes can perceive delay at low as 9# 100ms, but since we use thread time instead of wall-time, we reduce the 10# threshold further to 50ms to make room for other OS's activities. 11USER_PERCEIVABLE_DELAY_THRESHOLD_MS = 50 12 13 14class _MainthreadJankStat(object): 15 """A small wrapper class for storing mainthread jank stats computed for 16 single record. 17 """ 18 19 def __init__(self): 20 self.sum_big_top_slices_thread_time = 0 21 self.biggest_top_slice_thread_time = 0 22 23 24def _ComputeMainthreadJankStatsForRecord(renderer_thread, record): 25 """Computes the mainthread jank stat on a record range. 26 27 Returns: 28 An instance of _MainthreadJankStat, which has: 29 30 sum_big_top_slices_thread_time is the total thread duration of all top 31 slices whose thread time ranges overlapped with (thread_start, thread_end) 32 and the overlapped thread duration is greater than or equal 33 USER_PERCEIVABLE_DELAY_THRESHOLD_MS. 34 35 biggest_top_slice_thread_time is the biggest thread duration of all 36 top slices whose thread time ranges overlapped with 37 (thread_start, thread_end). 38 39 Note: thread duration of each slices is computed using overlapped range 40 with (thread_start, thread_end). 41 """ 42 stat = _MainthreadJankStat() 43 for s in renderer_thread.toplevel_slices: 44 jank_thread_duration = record.GetOverlappedThreadTimeForSlice(s) 45 stat.biggest_top_slice_thread_time = max( 46 stat.biggest_top_slice_thread_time, jank_thread_duration) 47 if jank_thread_duration >= USER_PERCEIVABLE_DELAY_THRESHOLD_MS: 48 stat.sum_big_top_slices_thread_time += jank_thread_duration 49 return stat 50 51 52class MainthreadJankStats(object): 53 """ 54 Utility class for extracting main thread jank statistics from the timeline 55 (or other loggin facilities), and providing them in a common format to 56 classes that compute benchmark metrics from this data. 57 58 total_big_jank_thread_time is the total thread duration of all top 59 slices whose thread time ranges overlapped with any thread time ranges of 60 the records and the overlapped thread duration is greater than or equal 61 USER_PERCEIVABLE_DELAY_THRESHOLD_MS. 62 63 biggest_jank_thread_time is the biggest thread duration of all 64 top slices whose thread time ranges overlapped with any of records' thread 65 time ranges. 66 """ 67 68 def __init__(self, renderer_thread, interaction_records): 69 self._renderer_thread = renderer_thread 70 self._interaction_records = interaction_records 71 self._total_big_jank_thread_time = 0 72 self._biggest_jank_thread_time = 0 73 self._ComputeMainthreadJankStats() 74 75 @property 76 def total_big_jank_thread_time(self): 77 return self._total_big_jank_thread_time 78 79 @property 80 def biggest_jank_thread_time(self): 81 return self._biggest_jank_thread_time 82 83 def _ComputeMainthreadJankStats(self): 84 for record in self._interaction_records: 85 record_jank_stat = _ComputeMainthreadJankStatsForRecord( 86 self._renderer_thread, record) 87 self._total_big_jank_thread_time += ( 88 record_jank_stat.sum_big_top_slices_thread_time) 89 self._biggest_jank_thread_time = ( 90 max(self._biggest_jank_thread_time, 91 record_jank_stat.biggest_top_slice_thread_time)) 92