1# Copyright 2013 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 5import json 6import math 7import os 8 9from telemetry import benchmark 10from telemetry.core import util 11from telemetry.page import page_set 12from telemetry.page import page_test 13from telemetry.value import merge_values 14from telemetry.value import scalar 15 16 17def _GeometricMean(values): 18 """Compute a rounded geometric mean from an array of values.""" 19 if not values: 20 return None 21 # To avoid infinite value errors, make sure no value is less than 0.001. 22 new_values = [] 23 for value in values: 24 if value > 0.001: 25 new_values.append(value) 26 else: 27 new_values.append(0.001) 28 # Compute the sum of the log of the values. 29 log_sum = sum(map(math.log, new_values)) 30 # Raise e to that sum over the number of values. 31 mean = math.pow(math.e, (log_sum / len(new_values))) 32 # Return the rounded mean. 33 return int(round(mean)) 34 35 36SCORE_UNIT = 'score (bigger is better)' 37SCORE_TRACE_NAME = 'score' 38 39 40class _DomPerfMeasurement(page_test.PageTest): 41 def ValidateAndMeasurePage(self, page, tab, results): 42 try: 43 def _IsDone(): 44 return tab.GetCookieByName('__domperf_finished') == '1' 45 util.WaitFor(_IsDone, 600) 46 47 data = json.loads(tab.EvaluateJavaScript('__domperf_result')) 48 for suite in data['BenchmarkSuites']: 49 # Skip benchmarks that we didn't actually run this time around. 50 if len(suite['Benchmarks']) or suite['score']: 51 results.AddValue(scalar.ScalarValue( 52 results.current_page, '%s.%s' % (suite['name'], SCORE_TRACE_NAME), 53 SCORE_UNIT, suite['score'], important=False)) 54 finally: 55 tab.EvaluateJavaScript('document.cookie = "__domperf_finished=0"') 56 57 def DidRunTest(self, browser, results): 58 # Now give the geometric mean as the total for the combined runs. 59 combined = merge_values.MergeLikeValuesFromDifferentPages( 60 results.all_page_specific_values, 61 group_by_name_suffix=True) 62 combined_score = [x for x in combined if x.name == SCORE_TRACE_NAME][0] 63 total = _GeometricMean(combined_score.values) 64 results.AddSummaryValue( 65 scalar.ScalarValue(None, 'Total.' + SCORE_TRACE_NAME, SCORE_UNIT, 66 total)) 67 68 69@benchmark.Disabled('android', 'linux') 70class DomPerf(benchmark.Benchmark): 71 """A suite of JavaScript benchmarks for exercising the browser's DOM. 72 73 The final score is computed as the geometric mean of the individual results. 74 Scores are not comparable across benchmark suite versions and higher scores 75 means better performance: Bigger is better!""" 76 test = _DomPerfMeasurement 77 78 def CreatePageSet(self, options): 79 dom_perf_dir = os.path.join(util.GetChromiumSrcDir(), 'data', 'dom_perf') 80 run_params = [ 81 'Accessors', 82 'CloneNodes', 83 'CreateNodes', 84 'DOMDivWalk', 85 'DOMTable', 86 'DOMWalk', 87 'Events', 88 'Get+Elements', 89 'GridSort', 90 'Template' 91 ] 92 ps = page_set.PageSet(file_path=dom_perf_dir) 93 for param in run_params: 94 ps.AddPageWithDefaultRunNavigate( 95 'file://run.html?reportInJS=1&run=%s' % param) 96 return ps 97