blob: aabd5b84dd27ca4052a7743052a0810e028a401b [file] [log] [blame]
Patrik Höglundcb0b8742019-11-18 13:46:38 +01001#!/usr/bin/env python
2# Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3#
4# Use of this source code is governed by a BSD-style license
5# that can be found in the LICENSE file in the root of the source
6# tree. An additional intellectual property rights grant can be found
7# in the file PATENTS. All contributing project authors may
8# be found in the AUTHORS file in the root of the source tree.
9
10"""Upload data to the chrome perf dashboard via add_histograms endpoint."""
11
12import os
13import sys
14import logging
15
16SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
17CHECKOUT_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir, os.pardir))
18sys.path.insert(0, os.path.join(CHECKOUT_ROOT, 'third_party', 'catapult',
19 'tracing'))
20
21from tracing.value import histogram
22from tracing.value import histogram_set
23from tracing.value.diagnostics import generic_set
24from tracing.value.diagnostics import reserved_infos
25
26# Enums aren't supported in Chromium's python env, so do something similar:
27class ImprovementDirection(object):
28 DEFAULT = 1
29 BIGGER_IS_BETTER = 2
30 SMALLER_IS_BETTER = 3
31
32
33def MakeWebRtcHistogramSet(stats, commit_pos, commit_hash, master, bot,
34 test_suite, build_url):
35 """Converts a dict of stats into a list of points with additional info.
36
37 Args:
38 stats: A list of histograms to upload.
39 piper_revision: Baseline piper revision that the test was run on.
40 commit_hash: WebRTC commit hash that the test was run on.
41 master:
42 bot: Bot name as it will show up in the perf dashboard.
43 test_suite: Top-level identifier of the test for Chrome perf dashboard.
44 build_url: An URL pointing to the bot status page for this build.
45
46 Returns:
47 A histogram set in format that expect Chrome perf dashboard.
48 """
49 common_diagnostics = {
50 reserved_infos.MASTERS: master,
51 reserved_infos.BOTS: bot,
52 reserved_infos.POINT_ID: commit_pos,
53 reserved_infos.BENCHMARKS: test_suite,
54 reserved_infos.WEBRTC_REVISIONS: str(commit_hash),
55 reserved_infos.BUILD_URLS: build_url,
56 }
57
58 hs = histogram_set.HistogramSet()
59 for h in stats:
60 hs.AddHistogram(h)
61
62 for k, v in common_diagnostics.items():
63 hs.AddSharedDiagnosticToAllHistograms(k.name, generic_set.GenericSet([v]))
64
65 return hs
66
67
68def LoadHistograms(data):
69 """Load histograms from Chart JSON format json file and fix them for API.
70
71 Args:
72 data: parsed json object of Chart JSON format.
73
74 Raises:
75 RuntimeError: input data contains standard deviation section.
76 Returns:
77 list of loaded histograms.
78 """
79 stats = []
80 for metric, story in data['charts'].items():
81 for story_name, story_desc in story.items():
82 units = story_desc['units'].strip()
83 if 'std' in story_desc:
84 # TODO(bugs.webrtc.org/11084): This seems bad to throw away?
85 logging.debug('std is not supported, specify list of values instead.')
86
87 if 'value' in story_desc:
88 values = [story_desc['value']]
89 else:
90 values = list(story_desc['values'])
91
92 improvement_direction = ImprovementDirection.DEFAULT
93 if 'improvement_direction' in story_desc:
94 if story_desc['improvement_direction'] == 'bigger_is_better':
95 improvement_direction = ImprovementDirection.BIGGER_IS_BETTER
96 elif story_desc['improvement_direction'] == 'smaller_is_better':
97 improvement_direction = ImprovementDirection.SMALLER_IS_BETTER
98 if 'higher_is_better' in story_desc:
99 if story_desc['higher_is_better']:
100 improvement_direction = ImprovementDirection.BIGGER_IS_BETTER
101 else:
102 improvement_direction = ImprovementDirection.SMALLER_IS_BETTER
103
104 new_metric, new_units, new_values = _FixUnits(metric, units, values)
105 h = _BuildHistogram(new_metric, story_name, new_units, new_values,
106 improvement_direction)
107 stats.append(h)
108 return stats
109
110
111def _FixUnits(metric_name, units, values):
112 """Fix units and metric name with values if required.
113
114 Args:
115 metric_name: origin metric name
116 units: raw trimmed units
117 values: origin values
118
119 Returns:
120 (metric_name, units, values) triple with fixed content
121 """
122 if units == 'bps':
123 return metric_name, 'bytesPerSecond', [v / 8.0 for v in values]
124 elif units == 'dB':
125 return metric_name + '_dB', 'unitless', values
126 elif units == 'fps':
127 return metric_name + '_fps', 'Hz', values
128 elif units == 'frames':
129 return metric_name, 'count', values
130 elif units == 'ms':
131 return metric_name, 'msBestFitFormat', values
132 elif units == '%':
133 return metric_name + '_%', 'unitless', values
134 else:
135 return metric_name, units, values
136
137
138def _BuildHistogram(metric_name, story_name, units, values,
139 improvement_direction):
140 """Build histogram. Uses unitless for unsupported units."""
141 if units not in histogram.UNIT_NAMES:
142 logging.debug(
143 'Unsupported unit %s will be replaced by \'unitless\'', units)
144 units = 'unitless'
145 if improvement_direction is ImprovementDirection.BIGGER_IS_BETTER:
146 units = units + '_biggerIsBetter'
147 elif improvement_direction is ImprovementDirection.SMALLER_IS_BETTER:
148 units = units + '_smallerIsBetter'
149 h = histogram.Histogram(metric_name, units,
150 histogram.HistogramBinBoundaries.SINGULAR)
151 h.diagnostics[reserved_infos.STORIES.name] = generic_set.GenericSet(
152 [story_name])
153 h.CustomizeSummaryOptions({
154 'std': False,
155 'avg': False,
156 'count': False,
157 'max': False,
158 'min': False,
159 'sum': False
160 })
161 for v in values:
162 h.AddSample(v)
163 return h