1# Copyright 2017 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"""Helper methods for working with histograms and diagnostics.""" 5from __future__ import print_function 6from __future__ import division 7from __future__ import absolute_import 8 9import re 10 11from tracing.value.diagnostics import reserved_infos 12 13# List of non-TBMv2 chromium.perf Telemetry benchmarks 14_LEGACY_BENCHMARKS = [ 15 'blink_perf.bindings', 'blink_perf.canvas', 'blink_perf.css', 16 'blink_perf.dom', 'blink_perf.events', 'blink_perf.image_decoder', 17 'blink_perf.layout', 'blink_perf.owp_storage', 'blink_perf.paint', 18 'blink_perf.parser', 'blink_perf.shadow_dom', 'blink_perf.svg', 19 'cronet_perf_tests', 'dromaeo', 'dummy_benchmark.noisy_benchmark_1', 20 'dummy_benchmark.stable_benchmark_1', 'jetstream', 'kraken', 'octane', 21 'rasterize_and_record_micro.partial_invalidation', 22 'rasterize_and_record_micro.top_25', 'scheduler.tough_scheduling_cases', 23 'smoothness.desktop_tough_pinch_zoom_cases', 24 'smoothness.gpu_rasterization.polymer', 25 'smoothness.gpu_rasterization.top_25_smooth', 26 'smoothness.gpu_rasterization.tough_filters_cases', 27 'smoothness.gpu_rasterization.tough_path_rendering_cases', 28 'smoothness.gpu_rasterization.tough_pinch_zoom_cases', 29 'smoothness.gpu_rasterization.tough_scrolling_cases', 30 'smoothness.gpu_rasterization_and_decoding.image_decoding_cases', 31 'smoothness.image_decoding_cases', 'smoothness.key_desktop_move_cases', 32 'smoothness.key_mobile_sites_smooth', 'smoothness.key_silk_cases', 33 'smoothness.maps', 'smoothness.pathological_mobile_sites', 34 'smoothness.simple_mobile_sites', 35 'smoothness.sync_scroll.key_mobile_sites_smooth', 36 'smoothness.top_25_smooth', 'smoothness.tough_ad_cases', 37 'smoothness.tough_animation_cases', 'smoothness.tough_canvas_cases', 38 'smoothness.tough_filters_cases', 'smoothness.tough_image_decode_cases', 39 'smoothness.tough_path_rendering_cases', 40 'smoothness.tough_pinch_zoom_cases', 'smoothness.tough_scrolling_cases', 41 'smoothness.tough_texture_upload_cases', 'smoothness.tough_webgl_ad_cases', 42 'smoothness.tough_webgl_cases', 'speedometer', 'speedometer-future', 43 'speedometer2', 'speedometer2-future', 'start_with_url.cold.startup_pages', 44 'start_with_url.warm.startup_pages', 'thread_times.key_hit_test_cases', 45 'thread_times.key_idle_power_cases', 'thread_times.key_mobile_sites_smooth', 46 'thread_times.key_noop_cases', 'thread_times.key_silk_cases', 47 'thread_times.simple_mobile_sites', 'thread_times.tough_compositor_cases', 48 'thread_times.tough_scrolling_cases', 'v8.detached_context_age_in_gc' 49] 50_STATS_BLACKLIST = ['std', 'count', 'max', 'min', 'sum'] 51 52SUITE_LEVEL_SPARSE_DIAGNOSTIC_NAMES = set([ 53 reserved_infos.ARCHITECTURES.name, 54 reserved_infos.BENCHMARKS.name, 55 reserved_infos.BENCHMARK_DESCRIPTIONS.name, 56 reserved_infos.BOTS.name, 57 reserved_infos.BUG_COMPONENTS.name, 58 reserved_infos.DOCUMENTATION_URLS.name, 59 reserved_infos.GPUS.name, 60 reserved_infos.MASTERS.name, 61 reserved_infos.MEMORY_AMOUNTS.name, 62 reserved_infos.OS_NAMES.name, 63 reserved_infos.OS_VERSIONS.name, 64 reserved_infos.OWNERS.name, 65 reserved_infos.PRODUCT_VERSIONS.name, 66]) 67 68HISTOGRAM_LEVEL_SPARSE_DIAGNOSTIC_NAMES = set([ 69 reserved_infos.DEVICE_IDS.name, 70 reserved_infos.STORIES.name, 71 reserved_infos.STORYSET_REPEATS.name, 72 reserved_infos.STORY_TAGS.name, 73]) 74 75SPARSE_DIAGNOSTIC_NAMES = SUITE_LEVEL_SPARSE_DIAGNOSTIC_NAMES.union( 76 HISTOGRAM_LEVEL_SPARSE_DIAGNOSTIC_NAMES) 77 78ADD_HISTOGRAM_RELATED_DIAGNOSTICS = SPARSE_DIAGNOSTIC_NAMES.union( 79 set([ 80 reserved_infos.BUILD_URLS.name, 81 reserved_infos.CHROMIUM_COMMIT_POSITIONS.name, 82 reserved_infos.LOG_URLS.name, 83 reserved_infos.POINT_ID.name, 84 reserved_infos.SUMMARY_KEYS.name, 85 reserved_infos.TRACE_URLS.name, 86 ])) 87 88 89def EscapeName(name): 90 """Escapes a trace name so it can be stored in a row. 91 92 Args: 93 name: A string representing a name. 94 95 Returns: 96 An escaped version of the name. 97 """ 98 return re.sub(r'[\:|=/#&,]', '_', name) 99 100 101def ComputeTestPath(hist, ignore_grouping_label=False): 102 # If a Histogram represents a summary across multiple stories, then its 103 # 'stories' diagnostic will contain the names of all of the stories. 104 # If a Histogram is not a summary, then its 'stories' diagnostic will contain 105 # the singular name of its story. 106 is_summary = list(hist.diagnostics.get(reserved_infos.SUMMARY_KEYS.name, [])) 107 108 grouping_label = GetGroupingLabelFromHistogram( 109 hist) if not ignore_grouping_label else None 110 111 is_ref = hist.diagnostics.get(reserved_infos.IS_REFERENCE_BUILD.name) 112 if is_ref and len(is_ref) == 1: 113 is_ref = is_ref.GetOnlyElement() 114 115 story_name = hist.diagnostics.get(reserved_infos.STORIES.name) 116 if story_name and len(story_name) == 1: 117 story_name = story_name.GetOnlyElement() 118 else: 119 story_name = None 120 121 return ComputeTestPathFromComponents( 122 hist.name, 123 grouping_label=grouping_label, 124 story_name=story_name, 125 is_summary=is_summary, 126 is_ref=is_ref) 127 128 129def ComputeTestPathFromComponents(hist_name, 130 grouping_label=None, 131 story_name=None, 132 is_summary=None, 133 is_ref=False, 134 needs_escape=True): 135 path = hist_name or '' 136 137 if grouping_label and (not is_summary 138 or reserved_infos.STORY_TAGS.name in is_summary): 139 path += '/' + grouping_label 140 141 if story_name and not is_summary: 142 if needs_escape: 143 escaped_story_name = EscapeName(story_name) 144 path += '/' + escaped_story_name 145 else: 146 path += '/' + story_name 147 if is_ref: 148 path += '_ref' 149 elif is_ref: 150 path += '/ref' 151 152 return path 153 154 155def GetGroupingLabelFromHistogram(hist): 156 tags = hist.diagnostics.get(reserved_infos.STORY_TAGS.name) or [] 157 158 tags_to_use = [t.split(':') for t in tags if ':' in t] 159 160 return '_'.join(v for _, v in sorted(tags_to_use)) 161 162 163def IsLegacyBenchmark(benchmark_name): 164 return benchmark_name in _LEGACY_BENCHMARKS 165 166 167def ShouldFilterStatistic(test_name, benchmark_name, stat_name): 168 if test_name == 'benchmark_total_duration': 169 return True 170 if benchmark_name.startswith( 171 'memory') and not benchmark_name.startswith('memory.long_running'): 172 if 'memory:' in test_name and stat_name in _STATS_BLACKLIST: 173 return True 174 if benchmark_name.startswith('memory.long_running'): 175 value_name = '%s_%s' % (test_name, stat_name) 176 return not _ShouldAddMemoryLongRunningValue(value_name) 177 if benchmark_name == 'media.desktop' or benchmark_name == 'media.mobile': 178 value_name = '%s_%s' % (test_name, stat_name) 179 return not _ShouldAddMediaValue(value_name) 180 if benchmark_name.startswith('system_health'): 181 if stat_name in _STATS_BLACKLIST: 182 return True 183 return False 184 185 186def _ShouldAddMediaValue(value_name): 187 media_re = re.compile( 188 r'(?<!dump)(?<!process)_(std|count|max|min|sum|pct_\d{4}(_\d+)?)$') 189 return not media_re.search(value_name) 190 191 192def _ShouldAddMemoryLongRunningValue(value_name): 193 v8_re = re.compile( 194 r'renderer_processes:' 195 r'(reported_by_chrome:v8|reported_by_os:system_memory:[^:]+$)') 196 if 'memory:chrome' in value_name: 197 return ('renderer:subsystem:v8' in value_name 198 or 'renderer:vmstats:overall' in value_name 199 or bool(v8_re.search(value_name))) 200 return 'v8' in value_name 201