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 5"""PeaceKeeper benchmark suite. 6 7Peacekeeper measures browser's performance by testing its JavaScript 8functionality. JavaScript is a widely used programming language used in the 9creation of modern websites to provide features such as animation, navigation, 10forms and other common requirements. By measuring a browser's ability to handle 11commonly used JavaScript functions Peacekeeper can evaluate its performance. 12Peacekeeper scores are measured in operations per second or rendered frames per 13second depending on the test. Final Score is computed by calculating geometric 14mean of individual tests scores. 15""" 16 17from telemetry import test 18from telemetry.page import page_measurement 19from telemetry.page import page_set 20from telemetry.util import statistics 21from telemetry.value import merge_values 22from telemetry.value import scalar 23 24class _PeaceKeeperMeasurement(page_measurement.PageMeasurement): 25 26 def WillNavigateToPage(self, page, tab): 27 page.script_to_evaluate_on_commit = """ 28 var __results = {}; 29 var _done = false; 30 var __real_log = window.console.log; 31 var test_frame = null; 32 var benchmark = null; 33 window.console.log = function(msg) { 34 if (typeof(msg) == "string" && (msg.indexOf("benchmark")) == 0) { 35 test_frame = document.getElementById("testFrame"); 36 benchmark = test_frame.contentWindow.benchmark; 37 test_frame.contentWindow.onbeforeunload = {}; 38 if ((msg.indexOf("Submit ok.")) != -1) { 39 _done = true; 40 __results["test"] = benchmark.testObjectName; 41 __results["score"] = benchmark.test.result; 42 if (typeof(benchmark.test.unit) != "undefined") { 43 __results["unit"] = benchmark.test.unit; 44 } else { 45 __results["unit"] = benchmark.test.isFps ? "fps" : "ops"; 46 } 47 } 48 } 49 __real_log.apply(this, [msg]); 50 } 51 """ 52 53 def MeasurePage(self, _, tab, results): 54 tab.WaitForJavaScriptExpression('_done', 600) 55 result = tab.EvaluateJavaScript('__results') 56 57 results.Add('Score', 'score', int(result['score']), result['test'], 58 'unimportant') 59 60 def DidRunTest(self, browser, results): 61 # Calculate geometric mean as the total for the combined tests. 62 combined = merge_values.MergeLikeValuesFromDifferentPages( 63 results.all_page_specific_values, 64 group_by_name_suffix=True) 65 combined_score = [x for x in combined if x.name == 'Score'][0] 66 total = statistics.GeometricMean(combined_score.values) 67 results.AddSummaryValue( 68 scalar.ScalarValue(None, 'Total.Score', 'score', total)) 69 70 71class PeaceKeeperBenchmark(test.Test): 72 """A base class for Peackeeper benchmarks.""" 73 test = _PeaceKeeperMeasurement 74 75 def CreatePageSet(self, options): 76 """Makes a PageSet for PeaceKeeper benchmarks.""" 77 # Subclasses are expected to define a class member called query_param. 78 if not hasattr(self, 'test_param'): 79 raise NotImplementedError('test_param not in PeaceKeeper benchmark.') 80 81 ps = page_set.PageSet( 82 archive_data_file='../page_sets/data/peacekeeper_%s.json' % self.tag, 83 make_javascript_deterministic=False) 84 for test_name in self.test_param: 85 ps.AddPageWithDefaultRunNavigate( 86 ('http://peacekeeper.futuremark.com/run.action?debug=true&' 87 'repeat=false&forceSuiteName=%s&forceTestName=%s') % 88 (self.tag, test_name)) 89 return ps 90 91 92class PeaceKeeperRender(PeaceKeeperBenchmark): 93 """PeaceKeeper rendering benchmark suite. 94 95 These tests measure your browser's ability to render and modify specific 96 elements used in typical web pages. Rendering tests manipulate the DOM tree in 97 real-time. The tests measure display updating speed (frames per seconds). 98 """ 99 tag = 'render' 100 test_param = ['renderGrid01', 101 'renderGrid02', 102 'renderGrid03', 103 'renderPhysics' 104 ] 105 106 107class PeaceKeeperData(PeaceKeeperBenchmark): 108 """PeaceKeeper Data operations benchmark suite. 109 110 These tests measure your browser's ability to add, remove and modify data 111 stored in an array. The Data suite consists of two tests: 112 1. arrayCombined: This test uses all features of the JavaScript Array object. 113 This is a technical test that is not based on profiled data. 114 The source data are different sized arrays of numbers. 115 2. arrayWeighted: This test is similar to 'arrayCombined', but the load is 116 balanced based on profiled data. The source data is a list of all the 117 countries in the world. 118 """ 119 120 tag = 'array' 121 test_param = ['arrayCombined01', 122 'arrayWeighted' 123 ] 124 125 126class PeaceKeeperDom(PeaceKeeperBenchmark): 127 """PeaceKeeper DOM operations benchmark suite. 128 129 These tests emulate the methods used to create typical dynamic webpages. 130 The DOM tests are based on development experience and the capabilities of the 131 jQuery framework. 132 1. domGetElements: This test uses native DOM methods getElementById and 133 getElementsByName. The elements are not modified. 134 2. domDynamicCreationCreateElement: A common use of DOM is to dynamically 135 create content with JavaScript, this test measures creating objects 136 individually and then appending them to DOM. 137 3. domDynamicCreationInnerHTML: This test is similarl to the previous one, 138 but uses the innerHTML-method. 139 4. domJQueryAttributeFilters: This test does a DOM query with jQuery. 140 It searches elements with specific attributes. 141 5. domJQueryBasicFilters: This test uses filters to query elements from DOM. 142 6. domJQueryBasics: This test queries elements from DOM with basic methods. 143 It is similar to domGetElements, but uses jQuery rather than native methods. 144 7. domJQueryContentFilters: Query elements based on content. This does string 145 searching and these methods are assumed to be time consuming. 146 8. domJQueryHierarchy: Query elements based on hierarchy, such as getting 147 sibling, parent or child nodes from a DOM tree. 148 9. domQueryselector: QuerySelector, which allows JavaScript to search elements 149 from the DOM tree directly without the need to iterate the whole tree 150 through domGetElements. 151 """ 152 153 tag = 'dom' 154 test_param = ['domGetElements', 155 'domDynamicCreationCreateElement', 156 'domDynamicCreationInnerHTML', 157 'domJQueryAttributeFilters', 158 'domJQueryBasicFilters', 159 'domJQueryBasics', 160 'domJQueryContentFilters', 161 'domJQueryHierarchy', 162 'domQueryselector' 163 ] 164 165 166class PeaceKeeperTextParsing(PeaceKeeperBenchmark): 167 """PeaceKeeper Text Parsing benchmark suite. 168 169 These tests measure your browser's performance in typical text manipulations 170 such as using a profanity filter for chats, browser detection and form 171 validation. 172 1. stringChat: This test removes swearing from artificial chat messages. 173 Test measures looping and string replace-method. 174 2. stringDetectBrowser: This test uses string indexOf-method to detect browser 175 and operating system. 176 3. stringFilter: This test filters a list of movies with a given keyword. 177 The behaviour is known as filtering select or continuous filter. It's used 178 to give real time suggestions while a user is filling input fields. 179 The test uses simple regular expressions. 180 4. stringValidateForm: This test uses complex regular expressions to validate 181 user input. 182 5. stringWeighted: This is an artificial test. Methods used and their 183 intensities are chosen based on profiled data. 184 """ 185 186 tag = 'string' 187 test_param = ['stringChat', 188 'stringDetectBrowser', 189 'stringFilter', 190 'stringWeighted', 191 'stringValidateForm' 192 ] 193 194 195class PeaceKeeperHTML5Canvas(PeaceKeeperBenchmark): 196 """PeaceKeeper HTML5 Canvas benchmark suite. 197 198 These tests use HTML5 Canvas, which is a web technology for drawing and 199 manipulating graphics without external plug-ins. 200 1. experimentalRipple01: Simulates a 'water ripple' effect by using HTML 5 201 Canvas. It measures the browser's ability to draw individual pixels. 202 2. experimentalRipple02: Same test as 'experimentalRipple01', but with a 203 larger canvas and thus a heavier workload. 204 """ 205 206 tag = 'experimental' 207 test_param = ['experimentalRipple01', 208 'experimentalRipple02' 209 ] 210 211 212class PeaceKeeperHTML5Capabilities(PeaceKeeperBenchmark): 213 """PeaceKeeper HTML5 Capabilities benchmark suite. 214 215 These tests checks browser HTML5 capabilities support for WebGL, Video 216 foramts, simple 2D sprite based games and web worker. 217 This benchmark only tests HTML5 capability and thus is not calculate into the 218 overall score. 219 1. HTML5 - WebGL: WebGL allows full blown 3D graphics to be rendered in a 220 browser without the need for any external plug-ins. 221 a) webglSphere 222 2. HTML5 - Video: hese tests find out which HTML5 video formats are supposed 223 by your browser. Peacekeeper only checks if your browser is able to play a 224 specific format, no other valuation is done. 225 a) videoCodecH264 226 b) videoCodecTheora 227 c) videoCodecWebM 228 d) videoPosterSupport 229 3.HTML5 - Web Worker: These tests use HTML5 Web Worker, which allows 230 JavaScript to multhread - ie. the ability to perform multiple actions 231 concurrently. 232 a) workerContrast01 233 b) workerContrast02 234 4. HTML5 - Game: This test simulates a simple 2D, sprite-based game. 235 The test itself is the real game, and what is shown is a recorded play. 236 a) gamingSpitfire 237 """ 238 239 tag = 'html5' 240 test_param = ['webglSphere', 241 'gamingSpitfire', 242 'videoCodecH264', 243 'videoCodecTheora', 244 'videoCodecWebM', 245 'videoPosterSupport', 246 'workerContrast01', 247 'workerContrast02' 248 ] 249