| #!/usr/bin/env python |
| # Copyright 2018 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. |
| """ |
| Run this script to generate the alert configs for memory benchmarks and |
| metrics to keep track of. |
| |
| After making changes to this script and running it, make sure to actually |
| update the respective anomaly configs and sheriff rotations as needed. |
| """ |
| from __future__ import print_function |
| import collections |
| |
| |
| ANOMALY_CONFIGS_URL = 'https://chromeperf.appspot.com/edit_anomaly_configs' |
| SHERIFFS_URL = 'https://chromeperf.appspot.com/edit_sheriffs' |
| |
| |
| _MemoryAlert = collections.namedtuple('_MemoryAlert', [ |
| 'master', 'builder', 'benchmark', 'browser', 'process', |
| 'reported_by', 'allocator', 'size', 'story', 'config', 'rotation']) |
| |
| |
| # Map from short to full sheriff rotation names. |
| ROTATIONS = { |
| 'chromium': 'Chromium Perf Sheriff', |
| 'v8-memory': 'V8 Memory Perf Sheriff', |
| } |
| |
| |
| class MemoryAlert(_MemoryAlert): |
| __slots__ = () |
| |
| def __new__(cls, **kwargs): |
| kwargs.setdefault('master', 'ChromiumPerf') |
| kwargs.setdefault('builder', '*') |
| kwargs.setdefault('benchmark', '*') |
| kwargs.setdefault('browser', 'chrome') |
| kwargs.setdefault('process', 'all_processes') |
| kwargs.setdefault('reported_by', '*') |
| kwargs.setdefault('allocator', '*') |
| kwargs.setdefault('size', '*') |
| kwargs.setdefault('story', '*/*') |
| kwargs.setdefault('config', 'memory_above_64k') |
| kwargs.setdefault('rotation', 'chromium') |
| return super(MemoryAlert, cls).__new__(cls, **kwargs) |
| |
| def __str__(self): |
| return '/'.join([self.master, self.builder, self.benchmark, self.metric, |
| self.story]) |
| |
| @property |
| def metric(self): |
| return 'memory:%s:%s:reported_by_%s:%s:%s_size_avg' % ( |
| self.browser, self.process, self.reported_by, self.allocator, |
| self.size) |
| |
| def Clone(self, **kwargs): |
| """Make a copy of this alert with some fields updated.""" |
| new_args = self._asdict() |
| new_args.update(kwargs) |
| # This makes sure we return a new object of the correct type; otherwise |
| # pyling gets confused if we try to use namedtuple._replace. |
| return type(self)(**new_args) |
| |
| |
| # Default settings for metrics reported by Chrome and OS probes. |
| # TODO(crbug.com/736506): For Chrome metrics we ideally want to alert on |
| # allocated_objects_size rather than effective_size, since the former tends to |
| # be a more stable metric. However, not all allocators report allocated_objects |
| # and some teams (e.g. v8) want to keep effective_size alerts regardless. |
| CHROME_ALLOCATED = MemoryAlert(reported_by='chrome', size='allocated_objects') |
| CHROME_EFFECTIVE = MemoryAlert(reported_by='chrome', size='effective') |
| OS_METRIC = MemoryAlert(reported_by='os', size='proportional_resident') |
| |
| # Common metrics to alert on for all desktop and mobile configurations. |
| DEFAULT_ALERTS = ( |
| # Metrics reporting allocated_objects. |
| CHROME_ALLOCATED.Clone(allocator='java_heap', config='memory_above_1m'), |
| CHROME_ALLOCATED.Clone(allocator='malloc'), |
| CHROME_ALLOCATED.Clone(allocator='v8', rotation='v8-memory'), |
| # Metrics with no allocated_objects or where we also want effective_size. |
| CHROME_EFFECTIVE.Clone(allocator='cc'), |
| CHROME_EFFECTIVE.Clone(allocator='gpu'), |
| CHROME_EFFECTIVE.Clone(allocator='malloc'), |
| CHROME_EFFECTIVE.Clone(allocator='skia'), |
| CHROME_EFFECTIVE.Clone(allocator='v8', rotation='v8-memory'), |
| # Our top-level source of truth. |
| OS_METRIC.Clone(allocator='system_memory', size='private_footprint'), |
| ) |
| |
| # Extra metrics to alert on for Android System Health reporting purposes. |
| ANDROID_ALERTS = ( |
| # Java Heap |
| OS_METRIC.Clone(allocator='system_memory:java_heap', |
| config='memory_above_1m'), |
| # Native Heap |
| OS_METRIC.Clone(allocator='system_memory:native_heap'), |
| # Private Dirty |
| OS_METRIC.Clone(allocator='system_memory', size='private_dirty'), |
| # Android Graphics |
| OS_METRIC.Clone(allocator='gpu_memory'), |
| # Overall PSS |
| OS_METRIC.Clone(allocator='system_memory'), |
| ) |
| |
| |
| def ExportAlerts(filename, alerts, url, instructions): |
| with open(filename, 'w') as f: |
| print('-', filename) |
| print('# Please visit:', url, file=f) |
| print('# And', instructions, file=f) |
| for alert in alerts: |
| print(alert, file=f) |
| |
| def main(): |
| alerts = [] |
| |
| ## Desktop ## |
| |
| # Alerts for system_health.memory_desktop. |
| for alert in DEFAULT_ALERTS: |
| alerts.append(alert.Clone(benchmark='system_health.memory_desktop')) |
| |
| # Alerts for memory.desktop. |
| for alert in DEFAULT_ALERTS: |
| alerts.append(alert.Clone(benchmark='memory.desktop', story='*')) |
| |
| ## Mobile ## |
| |
| # Alerts for system_health.memory_mobile. |
| for master in ('ChromiumPerf', 'ClankInternal'): |
| for browser in ('chrome', 'webview'): |
| for alert in DEFAULT_ALERTS + ANDROID_ALERTS: |
| alerts.append(alert.Clone( |
| benchmark='system_health.memory_mobile', |
| master=master, browser=browser)) |
| |
| # Alerts for memory.top_10_mobile. |
| for master in ('ChromiumPerf', 'ClankInternal'): |
| for browser in ('chrome', 'webview'): |
| for alert in DEFAULT_ALERTS + ANDROID_ALERTS: |
| alerts.append(alert.Clone( |
| benchmark='memory.top_10_mobile', master=master, browser=browser)) |
| |
| # Alerts for memory.dual_browser_test. |
| for browser in ('chrome', 'webview'): |
| for alert in DEFAULT_ALERTS: |
| alerts.append(alert.Clone( |
| benchmark='memory.dual_browser_test', |
| master='ClankInternal', browser=browser)) |
| |
| # Export anomaly and sheriff rotation configs. |
| for config in set(a.config for a in alerts): |
| ExportAlerts( |
| 'anomalies-%s.txt' % config, |
| (a for a in alerts if a.config == config), |
| ANOMALY_CONFIGS_URL, |
| "replace the config '%s' with the following alerts:" % config) |
| |
| for rotation in set(a.rotation for a in alerts): |
| ExportAlerts( |
| 'sheriff-%s.txt' % rotation, |
| (a for a in alerts if a.rotation == rotation), |
| SHERIFFS_URL, |
| "replace memory alerts *only* in the config '%s' with:" |
| % ROTATIONS[rotation]) |
| |
| if __name__ == '__main__': |
| main() |