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.
4import collections
5import json
6import os
7
8from metrics import power
9from telemetry import benchmark
10from telemetry.page import page_set
11from telemetry.page import page_test
12from telemetry.value import list_of_scalar_values
13
14
15_URL = 'http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html'
16
17DESCRIPTIONS = {
18    '3d-cube':
19        'Pure JavaScript computations of the kind you might use to do 3d '
20        'rendering, but without the rendering. This ends up mostly hitting '
21        'floating point math and array access.',
22    '3d-morph':
23        'Pure JavaScript computations of the kind you might use to do 3d '
24        'rendering, but without the rendering. This ends up mostly hitting '
25        'floating point math and array access.',
26    '3d-raytrace':
27        'Pure JavaScript computations of the kind you might use to do 3d '
28        'rendering, but without the rendering. This ends up mostly hitting '
29        'floating point math and array access.',
30    'access-binary-trees': 'Array, object property and variable access.',
31    'access-fannkuch': 'Array, object property and variable access.',
32    'access-nbody': 'Array, object property and variable access.',
33    'access-nsieve': 'Array, object property and variable access.',
34    'bitops-3bit-bits-in-byte':
35        'Bitwise operations, these can be useful for various things '
36        'including games, mathematical computations, and various kinds of '
37        'encoding/decoding. It\'s also the only kind of math in JavaScript '
38        'that is done as integer, not floating point.',
39    'bitops-bits-in-byte':
40        'Bitwise operations, these can be useful for various things '
41        'including games, mathematical computations, and various kinds of '
42        'encoding/decoding. It\'s also the only kind of math in JavaScript '
43        'that is done as integer, not floating point.',
44    'bitops-bitwise-and':
45        'Bitwise operations, these can be useful for various things '
46        'including games, mathematical computations, and various kinds of '
47        'encoding/decoding. It\'s also the only kind of math in JavaScript '
48        'that is done as integer, not floating point.',
49    'bitops-nsieve-bits':
50        'Bitwise operations, these can be useful for various things '
51        'including games, mathematical computations, and various kinds of '
52        'encoding/decoding. It\'s also the only kind of math in JavaScript '
53        'that is done as integer, not floating point.',
54    'controlflow-recursive':
55        'Control flow constructs (looping, recursion, conditionals). Right '
56        'now it mostly covers recursion, as the others are pretty well covered '
57        'by other tests.',
58    'crypto-aes': 'Real cryptography code related to AES.',
59    'crypto-md5': 'Real cryptography code related to MD5.',
60    'crypto-sha1': 'Real cryptography code related to SHA1.',
61    'date-format-tofte': 'Performance of JavaScript\'s "date" objects.',
62    'date-format-xparb': 'Performance of JavaScript\'s "date" objects.',
63    'math-cordic': 'Various mathematical type computations.',
64    'math-partial-sums': 'Various mathematical type computations.',
65    'math-spectral-norm': 'Various mathematical type computations.',
66    'regexp-dna': 'Regular expressions performance.',
67    'string-base64': 'String processing.',
68    'string-fasta': 'String processing',
69    'string-tagcloud': 'String processing code to generate a giant "tagcloud".',
70    'string-unpack-code': 'String processing code to extracting compressed JS.',
71    'string-validate-input': 'String processing.',
72}
73
74
75class _SunspiderMeasurement(page_test.PageTest):
76  def __init__(self):
77    super(_SunspiderMeasurement, self).__init__()
78    self._power_metric = None
79
80  def CustomizeBrowserOptions(self, options):
81    power.PowerMetric.CustomizeBrowserOptions(options)
82
83  def WillStartBrowser(self, platform):
84    self._power_metric = power.PowerMetric(platform)
85
86  def DidNavigateToPage(self, page, tab):
87    self._power_metric.Start(page, tab)
88
89  def ValidateAndMeasurePage(self, page, tab, results):
90    tab.WaitForJavaScriptExpression(
91        'window.location.pathname.indexOf("results.html") >= 0'
92        '&& typeof(output) != "undefined"', 300)
93
94    self._power_metric.Stop(page, tab)
95    self._power_metric.AddResults(tab, results)
96
97    js_get_results = 'JSON.stringify(output);'
98    js_results = json.loads(tab.EvaluateJavaScript(js_get_results))
99
100    # Below, r is a map of benchmark names to lists of result numbers,
101    # and totals is a list of totals of result numbers.
102    # js_results is: formatted like this:
103    # [
104    #   {'3d-cube': v1, '3d-morph': v2, ...},
105    #   {'3d-cube': v3, '3d-morph': v4, ...},
106    #   ...
107    # ]
108    r = collections.defaultdict(list)
109    totals = []
110    for result in js_results:
111      total = 0
112      for key, value in result.iteritems():
113        r[key].append(value)
114        total += value
115      totals.append(total)
116    for key, values in r.iteritems():
117      results.AddValue(list_of_scalar_values.ListOfScalarValues(
118          results.current_page, key, 'ms', values, important=False,
119          description=DESCRIPTIONS.get(key)))
120    results.AddValue(list_of_scalar_values.ListOfScalarValues(
121        results.current_page, 'Total', 'ms', totals,
122        description='Totals of run time for each different type of benchmark '
123                    'in sunspider'))
124
125
126class Sunspider(benchmark.Benchmark):
127  """Apple's SunSpider JavaScript benchmark."""
128  test = _SunspiderMeasurement
129
130  def CreatePageSet(self, options):
131    ps = page_set.PageSet(
132      archive_data_file='../page_sets/data/sunspider.json',
133      make_javascript_deterministic=False,
134      file_path=os.path.abspath(__file__))
135    ps.AddPageWithDefaultRunNavigate(_URL)
136    return ps
137