Avi Drissman | dfd88085 | 2022-09-15 20:11:09 | [diff] [blame] | 1 | # Copyright 2018 The Chromium Authors |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | """ Orderfile Generation and Testing |
| 5 | |
| 6 | This provides a suite of benchmarks for orderfile generation and testing based |
| 7 | on the mobile system health benchmarks. |
| 8 | |
| 9 | The orderfile_generation.training benchmark is meant to be run with an |
| 10 | orderfile instrumented build to produce function usage profiles. It can be |
| 11 | invoked as follows: |
| 12 | (CHROMIUM_OUTPUT_DIR=out/Instrumented; \ |
| 13 | ./tools/perf/run_benchmark --device=${YOUR_DEVICE_SN} --browser=exact \ |
| 14 | --browser-executable=${CHROMIUM_OUTPUT_DIR}/apks/Monochrome.apk \ |
| 15 | orderfile_generation.training) |
| 16 | |
| 17 | The orderfile_generation.testing benchmark has a smaller test set whose |
| 18 | benchmarks are distinct from those in orderfile_generation.training. Run it as |
| 19 | follows, note the --orderfile-memory-optimization flag is necessary only with |
| 20 | legacy orderfile builds of chrome. |
| 21 | (CHROMIUM_OUTPUT_DIR=out/Official; \ |
| 22 | ./tools/perf/run_benchmark --device=${YOUR_DEVICE_SN} --browser=exact \ |
| 23 | --browser-executable=${CHROMIUM_OUTPUT_DIR}/apks/Monochrome.apk \ |
| 24 | --extra-browser-args=--orderfile-memory-optimization \ |
| 25 | --results-label=${LABEL_CORRESPONDING_TO_YOUR_BUILD} \ |
| 26 | orderfile_generation.training) |
| 27 | |
| 28 | The orderfile_generation.variation.* benchmarks use a smaller training set so |
| 29 | that several test set variations can be produced. They are run as above but |
| 30 | using the following benchmark names. |
| 31 | orderfile_generation.variation.training |
| 32 | orderfile_generation.variation.testing0 |
| 33 | orderfile_generation.variation.testing1 |
| 34 | orderfile_generation.variation.testing2 |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 35 | |
| 36 | The orderfile_generation.debugging benchmark is a short benchmark of 3 stories |
| 37 | that is useful for debugging hardware and test setup problems. |
| 38 | """ |
| 39 | |
| 40 | import random |
| 41 | |
Rasika Navarange | 8a83680 | 2024-07-25 16:29:10 | [diff] [blame] | 42 | from benchmarks import system_health, speedometer3 |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 43 | from page_sets.system_health import platforms |
| 44 | from page_sets.system_health import system_health_stories |
| 45 | from telemetry import benchmark |
| 46 | from telemetry import story |
Monica Salama | 90b8f5b | 2019-04-25 11:10:38 | [diff] [blame] | 47 | from telemetry.timeline import chrome_trace_category_filter |
| 48 | from telemetry.timeline import chrome_trace_config |
| 49 | from telemetry.web_perf import timeline_based_measurement |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 50 | |
| 51 | |
| 52 | class OrderfileStorySet(story.StorySet): |
| 53 | """User stories for orderfile generation. |
| 54 | |
| 55 | The run set specified in the constructor splits the stories into training and |
| 56 | testing sets (or debugging, see the code for details). |
| 57 | """ |
| 58 | # Run set names. |
| 59 | TRAINING = 'training' |
| 60 | TESTING = 'testing' |
| 61 | DEBUGGING = 'debugging' |
| 62 | |
| 63 | _PLATFORM = 'mobile' |
| 64 | |
Peter Wen | 449e52e | 2024-06-20 10:14:21 | [diff] [blame] | 65 | _BLOCKLIST = set([ |
| 66 | # 0% success rate on arm (measured 2024 June). |
| 67 | 'browse:chrome:newtab:2019', |
| 68 | # 0% success rate on arm (measured 2024 June). |
| 69 | 'browse:chrome:omnibox:2019', |
| 70 | # 0% success rate on arm64, 2% on arm (measured 2024 June). |
| 71 | 'browse:news:globo:2019', |
| 72 | # 35% success rate on arm64, 64% on arm (measured 2024 June). |
| 73 | 'browse:news:washingtonpost:2019', |
| 74 | # 1% success rate on arm64, 17% on arm (measured 2024 June). |
| 75 | 'browse:shopping:amazon:2019', |
| 76 | # Carried over from previous blocklist. |
Matthew Cary | bcac190e | 2018-11-27 16:59:59 | [diff] [blame] | 77 | 'browse:tech:discourse_infinite_scroll:2018', |
Peter Wen | 449e52e | 2024-06-20 10:14:21 | [diff] [blame] | 78 | # Carried over from previous blocklist. |
Matthew Cary | 3c48bf62 | 2018-09-20 11:07:51 | [diff] [blame] | 79 | 'long_running:tools:gmail-background', |
Peter Wen | 449e52e | 2024-06-20 10:14:21 | [diff] [blame] | 80 | # Carried over from previous blocklist. |
| 81 | 'long_running:tools:gmail-foreground', |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 82 | ]) |
| 83 | |
| 84 | # The random seed used for reproducible runs. |
| 85 | SEED = 8675309 |
| 86 | |
| 87 | # These defaults are current best practice for production orderfiles. |
Matthew Cary | 52a49236 | 2018-09-17 10:56:05 | [diff] [blame] | 88 | DEFAULT_TRAINING = 25 |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 89 | DEFAULT_TESTING = 8 |
| 90 | DEFAULT_VARIATIONS = 1 |
| 91 | |
Matthew Cary | bcac190e | 2018-11-27 16:59:59 | [diff] [blame] | 92 | # The number of variations to use with the variation benchmarks. If this is |
| 93 | # changed, the number of OrderfileVariationTesting* classes declared below |
| 94 | # should change as well. |
| 95 | NUM_VARIATION_BENCHMARKS = 3 |
| 96 | |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 97 | def __init__(self, run_set, num_training=DEFAULT_TRAINING, |
| 98 | num_testing=DEFAULT_TESTING, num_variations=DEFAULT_VARIATIONS, |
| 99 | test_variation=0): |
| 100 | """Create an orderfile training or testing benchmark set. |
| 101 | |
| 102 | Args: |
| 103 | run_set: one of TRAINING, TESTING or DEBUGGING. |
| 104 | num_training: the number of benchmarks to use for training. |
| 105 | num_testing: the number of benchmarks to use in each test set. |
| 106 | num_variations: the number of test set variations. |
| 107 | test_variation: the test set variation to use. |
| 108 | """ |
| 109 | super(OrderfileStorySet, self).__init__( |
| 110 | archive_data_file=('../../page_sets/data/system_health_%s.json' % |
| 111 | self._PLATFORM), |
| 112 | cloud_storage_bucket=story.PARTNER_BUCKET) |
| 113 | |
| 114 | assert self._PLATFORM in platforms.ALL_PLATFORMS, '{} not in {}'.format( |
| 115 | self._PLATFORM, str(platforms.ALL_PLATFORMS)) |
| 116 | assert run_set in (self.TRAINING, self.TESTING, self.DEBUGGING) |
Wenbin Zhang | ec78a0e | 2022-07-11 19:04:46 | [diff] [blame] | 117 | assert 0 <= test_variation < num_variations |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 118 | |
| 119 | self._run_set = run_set |
| 120 | self._num_training = num_training |
| 121 | self._num_testing = num_testing |
| 122 | self._num_variations = num_variations |
| 123 | self._test_variation = test_variation |
| 124 | |
| 125 | # We want the story selection to be consistent across runs. |
| 126 | random.seed(self.SEED) |
| 127 | |
| 128 | for story_class in self.RunSetStories(): |
| 129 | # pylint: disable=E1102 |
| 130 | self.AddStory(story_class(self, take_memory_measurement=True)) |
| 131 | |
| 132 | def RunSetStories(self): |
| 133 | possible_stories = [ |
| 134 | s for s in system_health_stories.IterAllSystemHealthStoryClasses() |
Peter Wen | 449e52e | 2024-06-20 10:14:21 | [diff] [blame] | 135 | if (s.NAME not in self._BLOCKLIST and not s.ABSTRACT_STORY |
| 136 | and self._PLATFORM in s.SUPPORTED_PLATFORMS) |
| 137 | ] |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 138 | assert (self._num_training + self._num_variations * self._num_testing |
| 139 | <= len(possible_stories)), \ |
| 140 | 'We only have {} stories to work with, but want {} + {}*{}'.format( |
| 141 | len(possible_stories), self._num_training, self._num_variations, |
| 142 | self._num_testing) |
| 143 | |
| 144 | if self._run_set == self.DEBUGGING: |
| 145 | return random.sample(possible_stories, 3) |
| 146 | |
| 147 | random.shuffle(possible_stories) |
| 148 | if self._run_set == self.TRAINING: |
| 149 | return possible_stories[:self._num_training] |
Wenbin Zhang | ec78a0e | 2022-07-11 19:04:46 | [diff] [blame] | 150 | if self._run_set == self.TESTING: |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 151 | return possible_stories[ |
| 152 | (self._num_training + self._test_variation * self._num_testing): |
| 153 | (self._num_training + (self._test_variation + 1) * self._num_testing)] |
| 154 | assert False, 'Bad run set {}'.format(self._run_set) |
Wenbin Zhang | ec78a0e | 2022-07-11 19:04:46 | [diff] [blame] | 155 | return None |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 156 | |
| 157 | |
| 158 | class _OrderfileBenchmark(system_health.MobileMemorySystemHealth): |
| 159 | """Base benchmark for orderfile generation.""" |
| 160 | STORY_RUN_SET = None # Must be set in subclasses. |
| 161 | |
| 162 | def CreateStorySet(self, options): |
| 163 | return OrderfileStorySet(run_set=self.STORY_RUN_SET) |
| 164 | |
| 165 | |
| 166 | # pylint: disable=R0901 |
| 167 | @benchmark.Owner(emails=['[email protected]']) |
| 168 | class OrderfileTraining(_OrderfileBenchmark): |
| 169 | STORY_RUN_SET = OrderfileStorySet.TRAINING |
| 170 | |
| 171 | options = {'pageset_repeat': 2} |
| 172 | |
| 173 | @classmethod |
| 174 | def Name(cls): |
| 175 | return 'orderfile_generation.training' |
| 176 | |
| 177 | |
| 178 | # pylint: disable=R0901 |
| 179 | @benchmark.Owner(emails=['[email protected]']) |
| 180 | class OrderfileTesting(_OrderfileBenchmark): |
| 181 | STORY_RUN_SET = OrderfileStorySet.TESTING |
| 182 | |
| 183 | options = {'pageset_repeat': 7} |
| 184 | |
| 185 | @classmethod |
| 186 | def Name(cls): |
| 187 | return 'orderfile_generation.testing' |
| 188 | |
| 189 | |
| 190 | class _OrderfileVariation(system_health.MobileMemorySystemHealth): |
| 191 | """Orderfile generation with test set variations.""" |
| 192 | STORY_RUN_SET = None # Must be set in all subclasses. |
| 193 | TEST_VARIATION = 0 # Can be overridden testing subclasses. |
| 194 | |
| 195 | options = {'pageset_repeat': 7} |
| 196 | |
| 197 | def CreateStorySet(self, options): |
Matthew Cary | bcac190e | 2018-11-27 16:59:59 | [diff] [blame] | 198 | return OrderfileStorySet( |
| 199 | run_set=self.STORY_RUN_SET, |
| 200 | num_training=25, num_testing=8, |
| 201 | num_variations=OrderfileStorySet.NUM_VARIATION_BENCHMARKS, |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 202 | test_variation=self.TEST_VARIATION) |
| 203 | |
| 204 | @classmethod |
| 205 | def Name(cls): |
| 206 | if cls.STORY_RUN_SET == OrderfileStorySet.TESTING: |
| 207 | return 'orderfile_generation.variation.testing{}'.format( |
| 208 | cls.TEST_VARIATION) |
Wenbin Zhang | ec78a0e | 2022-07-11 19:04:46 | [diff] [blame] | 209 | if cls.STORY_RUN_SET == OrderfileStorySet.TRAINING: |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 210 | return 'orderfile_generation.variation.training' |
| 211 | assert False, 'Bad STORY_RUN_SET {}'.format(cls.STORY_RUN_SET) |
Wenbin Zhang | ec78a0e | 2022-07-11 19:04:46 | [diff] [blame] | 212 | return None |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 213 | |
| 214 | # pylint: disable=R0901 |
| 215 | @benchmark.Owner(emails=['[email protected]']) |
| 216 | class OrderfileVariationTraining(_OrderfileVariation): |
| 217 | STORY_RUN_SET = OrderfileStorySet.TRAINING |
| 218 | |
| 219 | |
| 220 | # pylint: disable=R0901 |
| 221 | @benchmark.Owner(emails=['[email protected]']) |
| 222 | class OrderfileVariationTesting0(_OrderfileVariation): |
| 223 | STORY_RUN_SET = OrderfileStorySet.TESTING |
| 224 | TEST_VARIATION = 0 |
| 225 | |
| 226 | |
| 227 | # pylint: disable=R0901 |
| 228 | @benchmark.Owner(emails=['[email protected]']) |
Matthew Cary | bcac190e | 2018-11-27 16:59:59 | [diff] [blame] | 229 | class OrderfileVariationTesting1(_OrderfileVariation): |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 230 | STORY_RUN_SET = OrderfileStorySet.TESTING |
| 231 | TEST_VARIATION = 1 |
| 232 | |
| 233 | |
| 234 | # pylint: disable=R0901 |
| 235 | @benchmark.Owner(emails=['[email protected]']) |
Matthew Cary | bcac190e | 2018-11-27 16:59:59 | [diff] [blame] | 236 | class OrderfileVariationTesting2(_OrderfileVariation): |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 237 | STORY_RUN_SET = OrderfileStorySet.TESTING |
| 238 | TEST_VARIATION = 2 |
| 239 | |
| 240 | |
| 241 | # pylint: disable=R0901 |
| 242 | @benchmark.Owner(emails=['[email protected]']) |
Matthew Cary | 717b551f4 | 2018-07-18 14:26:23 | [diff] [blame] | 243 | class OrderfileDebugging(_OrderfileBenchmark): |
| 244 | """A very short benchmark for debugging metrics collection.""" |
| 245 | STORY_RUN_SET = OrderfileStorySet.DEBUGGING |
| 246 | |
| 247 | options = {'pageset_repeat': 1} |
| 248 | |
| 249 | @classmethod |
| 250 | def Name(cls): |
| 251 | return 'orderfile_generation.debugging' |
Monica Salama | 90b8f5b | 2019-04-25 11:10:38 | [diff] [blame] | 252 | |
| 253 | @benchmark.Owner(emails=['[email protected]']) |
| 254 | class OrderfileMemory(system_health.MobileMemorySystemHealth): |
| 255 | """Benchmark for native code memory footprint evaluation.""" |
| 256 | class OrderfileMemoryStorySet(story.StorySet): |
Al Muthanna Athamina | f52cb33d | 2021-02-18 18:33:34 | [diff] [blame] | 257 | _STORY_SET = set(['browse:news:cnn:2021', 'browse:social:facebook:2019']) |
Monica Salama | 90b8f5b | 2019-04-25 11:10:38 | [diff] [blame] | 258 | |
| 259 | def __init__(self, platform, take_memory_measurement=True): |
| 260 | super(OrderfileMemory.OrderfileMemoryStorySet, self).__init__( |
| 261 | archive_data_file=('../../page_sets/data/system_health_%s.json' % |
| 262 | platform), |
| 263 | cloud_storage_bucket=story.PARTNER_BUCKET) |
| 264 | |
| 265 | assert platform in platforms.ALL_PLATFORMS |
Peter Wen | 449e52e | 2024-06-20 10:14:21 | [diff] [blame] | 266 | for story_cls in system_health_stories.IterAllSystemHealthStoryClasses(): |
| 267 | if (story_cls.ABSTRACT_STORY |
| 268 | or platform not in story_cls.SUPPORTED_PLATFORMS |
| 269 | or story_cls.NAME not in self._STORY_SET): |
Monica Salama | 90b8f5b | 2019-04-25 11:10:38 | [diff] [blame] | 270 | continue |
Peter Wen | 449e52e | 2024-06-20 10:14:21 | [diff] [blame] | 271 | self.AddStory(story_cls(self, take_memory_measurement)) |
Monica Salama | 90b8f5b | 2019-04-25 11:10:38 | [diff] [blame] | 272 | |
| 273 | |
| 274 | def CreateStorySet(self, options): |
| 275 | return self.OrderfileMemoryStorySet(platform=self.PLATFORM) |
| 276 | |
| 277 | def CreateCoreTimelineBasedMeasurementOptions(self): |
| 278 | cat_filter = chrome_trace_category_filter.ChromeTraceCategoryFilter( |
| 279 | filter_string='-*,disabled-by-default-memory-infra') |
| 280 | options = timeline_based_measurement.Options(cat_filter) |
| 281 | # options.config.enable_android_graphics_memtrack = True |
| 282 | options.SetTimelineBasedMetrics(['nativeCodeResidentMemoryMetric']) |
| 283 | # Setting an empty memory dump config disables periodic dumps. |
| 284 | options.config.chrome_trace_config.SetMemoryDumpConfig( |
| 285 | chrome_trace_config.MemoryDumpConfig()) |
| 286 | return options |
| 287 | |
| 288 | @classmethod |
| 289 | def Name(cls): |
| 290 | return 'orderfile.memory_mobile' |
Rasika Navarange | be615f0d | 2024-02-26 20:01:54 | [diff] [blame] | 291 | |
| 292 | |
| 293 | @benchmark.Owner(emails=['[email protected]']) |
| 294 | class OrderfileWebViewStartup(system_health.WebviewStartupSystemHealthBenchmark |
| 295 | ): |
| 296 | """Benchmark for orderfile generation with WebView startup profiles. |
| 297 | |
| 298 | We need this class to wrap the system_health.webview_startup benchmark so |
| 299 | we can apply the additional configs that trigger the devtools memory dump. |
| 300 | We rely on the devtools memory dump to collect the profiles, even though |
| 301 | this is a startup profile. The reason for this is so we can avoid rebuilding |
| 302 | the native library between benchmarks, as the memory_mobile based benchmarks |
| 303 | use this. Rebuilidng/relinking would make it difficult to merge the offsets. |
| 304 | TODO(b/326927766): remove the devtools_instrumentation_dumping compiler flag |
| 305 | so we can switch to startup profiling for webview startup. |
| 306 | """ |
| 307 | |
| 308 | def CreateStorySet(self, options): |
| 309 | return system_health_stories.SystemHealthBlankStorySet( |
| 310 | take_memory_measurement=True) |
| 311 | |
| 312 | def CreateCoreTimelineBasedMeasurementOptions(self): |
| 313 | cat_filter = chrome_trace_category_filter.ChromeTraceCategoryFilter( |
| 314 | filter_string='-*,disabled-by-default-memory-infra') |
| 315 | options = timeline_based_measurement.Options(cat_filter) |
| 316 | return options |
| 317 | |
| 318 | @classmethod |
| 319 | def Name(cls): |
| 320 | return 'orderfile_generation.webview_startup' |
| 321 | |
| 322 | |
| 323 | @benchmark.Owner(emails=['[email protected]']) |
| 324 | class OrderfileWebViewDebugging(OrderfileWebViewStartup): |
| 325 | """A very short benchmark for debugging metrics collection.""" |
| 326 | options = {'pageset_repeat': 1} |
| 327 | |
| 328 | @classmethod |
| 329 | def Name(cls): |
| 330 | return 'orderfile_generation.webview_startup_debugging' |
Rasika Navarange | 8a83680 | 2024-07-25 16:29:10 | [diff] [blame] | 331 | |
| 332 | |
| 333 | @benchmark.Owner(emails=['[email protected]']) |
| 334 | class OrderfileSpeedometer3(speedometer3.Speedometer3): |
| 335 | enable_systrace = True |
| 336 | take_memory_measurement = True |
Rasika Navarange | 1c90dc12 | 2024-08-08 10:58:58 | [diff] [blame] | 337 | options = {'pageset_repeat': 5} |
Rasika Navarange | 8a83680 | 2024-07-25 16:29:10 | [diff] [blame] | 338 | |
| 339 | @classmethod |
| 340 | def Name(cls): |
| 341 | return 'orderfile_generation.speedometer3' |
Rasika Navarange | 1c90dc12 | 2024-08-08 10:58:58 | [diff] [blame] | 342 | |
| 343 | |
| 344 | @benchmark.Owner(emails=['[email protected]']) |
| 345 | class OrderfileSpeedometer3Debugging(OrderfileSpeedometer3): |
| 346 | iteration_count = 1 |
| 347 | options = {'pageset_repeat': 1} |
| 348 | |
| 349 | @classmethod |
| 350 | def Name(cls): |
| 351 | return 'orderfile_generation.speedometer3_debugging' |