Chromium Code Reviews| Index: scripts/slave/recipe_modules/perf_try/bisect_results_json.py |
| diff --git a/scripts/slave/recipe_modules/perf_try/bisect_results_json.py b/scripts/slave/recipe_modules/perf_try/bisect_results_json.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e99045ff8ff3c2b13ce5f7924b3966e72730a1f4 |
| --- /dev/null |
| +++ b/scripts/slave/recipe_modules/perf_try/bisect_results_json.py |
| @@ -0,0 +1,97 @@ |
| +# Copyright 2015 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. |
| + |
| +# Note: The Perf Dashboard will display these data. Any changes here should |
| +# be updated on Perf Dashboard as well. |
| + |
| +_FAILED_INITIAL_CONFIDENCE_ABORT_REASON = ( |
| + 'The metric values for the initial "good" and "bad" revisions ' |
| + 'do not represent a clear regression.') |
| + |
| +_DIRECTION_OF_IMPROVEMENT_ABORT_REASON = ( |
| + 'The metric values for the initial "good" and "bad" revisions match the ' |
| + 'expected direction of improvement. Thus, likely represent an improvement ' |
| + 'and not a regression.') |
| + |
| + |
| +def get(api, config, results_without_patch, results_with_patch, labels): |
|
qyearsley
2016/01/11 22:49:43
Might it be potentially clearer if this module is
chrisphan
2016/01/14 00:53:26
Moved this to perf_try/api for consistency. This
|
| + """Returns the results as a dict.""" |
| + |
| + output_with_patch = results_with_patch.get('output') |
| + output_without_patch = results_without_patch.get('output') |
| + values_with_patch = results_with_patch.get('results').get('values') |
| + values_without_patch = results_without_patch.get('results').get('values') |
| + |
| + cloud_links_without_patch = api.parse_cloud_links(output_without_patch) |
| + cloud_links_with_patch = api.parse_cloud_links(output_with_patch) |
| + |
| + cloud_link = (cloud_links_without_patch['html'][0] |
| + if cloud_links_without_patch['html'] else '') |
| + |
| + results = { |
| + 'try_job_id': config.get('try_job_id'), |
| + 'status': 'completed', # TODO(chrisphan) Get partial results state. |
| + 'buildbot_log_url': '', # TODO(chrisphan) Get this. |
| + 'bisect_bot': '', # TODO(chrisphan): Get this. |
| + 'command': config.get('command'), |
| + 'metric': config.get('metric'), |
| + 'cloud_link': cloud_link, |
| + } |
| + |
| + if not values_with_patch or not values_without_patch: |
| + results['warnings'] = ['No values from test with patch, or none ' |
| + 'from test without patch.\n Output with patch:\n%s\n\nOutput without ' |
| + 'patch:\n%s' % (output_with_patch, output_without_patch)] |
| + return results |
| + |
| + mean_with_patch = api.m.math_utils.mean(values_with_patch) |
| + mean_without_patch = api.m.math_utils.mean(values_without_patch) |
| + |
| + stderr_with_patch = api.m.math_utils.standard_error(values_with_patch) |
| + stderr_without_patch = api.m.math_utils.standard_error( |
| + values_without_patch) |
| + |
| + profiler_with_patch = cloud_links_with_patch['profiler'] |
| + profiler_without_patch = cloud_links_without_patch['profiler'] |
| + |
| + # Calculate the % difference in the means of the 2 runs. |
| + relative_change = None |
| + std_err = None |
| + if mean_with_patch and values_with_patch: |
| + relative_change = api.m.math_utils.relative_change( |
| + mean_without_patch, mean_with_patch) * 100 |
| + std_err = api.m.math_utils.pooled_standard_error( |
| + [values_with_patch, values_without_patch]) |
| + |
| + if relative_change is not None and std_err is not None: |
| + data = [ |
| + ['Revision', 'Mean', 'Std.Error'], |
| + ['Patch', str(mean_with_patch), str(stderr_with_patch)], |
| + ['No Patch', str(mean_without_patch), str(stderr_without_patch)] |
| + ] |
| + results['change'] = relative_change |
| + results['std_err'] = std_err |
| + results['result'] = _pretty_table(data) |
| + |
| + profiler_links = [] |
| + if profiler_with_patch and profiler_without_patch: |
| + for i in xrange(len(profiler_with_patch)): # pragma: no cover |
| + profiler_links.append({ |
| + 'title': '%s[%d]' % (labels.get('profiler_link1'), i), |
| + 'link': profiler_with_patch[i] |
| + }) |
| + for i in xrange(len(profiler_without_patch)): # pragma: no cover |
| + profiler_links.append({ |
| + 'title': '%s[%d]' % (labels.get('profiler_link2'), i), |
| + 'link': profiler_without_patch[i] |
| + }) |
| + results['profiler_links'] = profiler_links |
| + |
| + return results |
| + |
| +def _pretty_table(data): |
| + results = [] |
| + for row in data: |
| + results.append('%-15s' * len(row) % tuple(row)) |
| + return '\n'.join(results) |