Commit aba26bbc authored by kjellander's avatar kjellander Committed by Commit bot

Revert of Add second batch JS benchmark and code generator (patchset #5...

Revert of Add second batch JS benchmark and code generator (patchset #5 id:60001 of https://codereview.chromium.org/1000203002/)

Reason for revert:
Breaks check_licenses on linux: https://build.chromium.org/p/chromium/builders/Linux/builds/59754/steps/check_licenses/logs/stdio

Notice: This was also caught by the trybot. Please don't commit manually - use the CQ instead.

Original issue's description:
> Add second batch JS benchmark and code generator
>
> This patch adds a "Second batch JS" benchmark and a code generator for
> creating synthetic Javascript content for the different variants of the
> benchmark.
>
> The benchmark flow is:
>
> 1. Load an initial page quickly. We also start a continuous animation
>    which gauges the responsiveness of the main thread.
> 2. Start loading Javascript asynchronously.
> 3. When the loading completes, wait 1 second and click on a button
>    which causes about 5% of the Javascript to execute.
>
> The aim is to keep the page responsive during loading and minimize the
> latency of the click handler. There are three variants with a small (15K),
> medium (150K) and large (1.2M) amount of Javascript.
>
> The generated Javascript consists of half top-level closures, half top-level
> functions, each of which calls a varying number of inner functions to
> perform arithmetic.
>
> Note that currently the benchmark only measures the responsiveness of the
> click handler, but eventually it will be able to track this over the entire
> interaction flow (crbug.com/460206).
>
> BUG=428350
> R=rmcilroy@chromium.org
>
> Committed: https://chromium.googlesource.com/chromium/src/+/b0a90f4b6c81fc65dd0c57ebc00b0ba6fe784b22

TBR=rmcilroy@chromium.org,skyostil@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=428350

Review URL: https://codereview.chromium.org/1019833002

Cr-Commit-Position: refs/heads/master@{#321342}
parent 6ce28f57
...@@ -369,35 +369,6 @@ class SynchronizedScrollOffsetPage(ToughSchedulingCasesPage): ...@@ -369,35 +369,6 @@ class SynchronizedScrollOffsetPage(ToughSchedulingCasesPage):
interaction.End() interaction.End()
class SecondBatchJsPage(ToughSchedulingCasesPage):
"""Why: For testing dynamically loading a large batch of Javascript and
running a part of it in response to user input.
"""
def __init__(self, page_set, variant='medium'):
super(SecondBatchJsPage, self).__init__(
url='file://tough_scheduling_cases/second_batch_js.html?%s' % variant,
page_set=page_set)
def RunPageInteractions(self, action_runner):
# Do a dummy tap to warm up the synthetic tap code path.
action_runner.TapElement(selector='div[id="spinner"]')
# Begin the action immediately because we want the page to update smoothly
# even while resources are being loaded.
action_runner.WaitForJavaScriptCondition('window.__ready !== undefined')
interaction = action_runner.BeginGestureInteraction('LoadAction')
action_runner.ExecuteJavaScript('kickOffLoading()')
action_runner.WaitForJavaScriptCondition('window.__ready')
# Click one second after the resources have finished loading.
action_runner.Wait(1)
action_runner.TapElement(selector='input[id="run"]')
# Wait for the test to complete.
action_runner.WaitForJavaScriptCondition('window.__finished')
interaction.End()
class ToughSchedulingCasesPageSet(page_set_module.PageSet): class ToughSchedulingCasesPageSet(page_set_module.PageSet):
"""Tough scheduler latency test cases.""" """Tough scheduler latency test cases."""
...@@ -470,7 +441,7 @@ class ToughSchedulingCasesPageSet(page_set_module.PageSet): ...@@ -470,7 +441,7 @@ class ToughSchedulingCasesPageSet(page_set_module.PageSet):
slow_handler=True, slow_handler=True,
bounce=False, bounce=False,
page_set=self)) page_set=self))
# Why: Slow handler blocks scroll start until touch ACK timeout # Why: Slow handler blocks scroll start until touch ACK timeout
self.AddUserStory(EmptyTouchHandlerPage( self.AddUserStory(EmptyTouchHandlerPage(
name='desktop_slow_handler', name='desktop_slow_handler',
desktop=True, desktop=True,
...@@ -493,7 +464,7 @@ class ToughSchedulingCasesPageSet(page_set_module.PageSet): ...@@ -493,7 +464,7 @@ class ToughSchedulingCasesPageSet(page_set_module.PageSet):
slow_handler=True, slow_handler=True,
bounce=True, bounce=True,
page_set=self)) page_set=self))
# Why: Scroll bounce with slow handler on desktop, blocks only once until # Why: Scroll bounce with slow handler on desktop, blocks only once until
# ACK timeout. # ACK timeout.
self.AddUserStory(EmptyTouchHandlerPage( self.AddUserStory(EmptyTouchHandlerPage(
name='bounce_desktop_slow_handler', name='bounce_desktop_slow_handler',
...@@ -501,9 +472,5 @@ class ToughSchedulingCasesPageSet(page_set_module.PageSet): ...@@ -501,9 +472,5 @@ class ToughSchedulingCasesPageSet(page_set_module.PageSet):
slow_handler=True, slow_handler=True,
bounce=True, bounce=True,
page_set=self)) page_set=self))
# Why: For measuring the latency of scroll-synchronized effects. # Why: For measuring the latency of scroll-synchronized effects.
self.AddUserStory(SynchronizedScrollOffsetPage(page_set=self)) self.AddUserStory(SynchronizedScrollOffsetPage(page_set=self))
# Why: Test loading a large amount of Javascript.
self.AddUserStory(SecondBatchJsPage(page_set=self, variant='light'))
self.AddUserStory(SecondBatchJsPage(page_set=self, variant='medium'))
self.AddUserStory(SecondBatchJsPage(page_set=self, variant='heavy'))
#!/bin/sh
readonly LIGHT_OPTS="\
--closure-count=10 \
--function-count=10 \
--inner-function-count=10 \
--function-call-count=1 \
--closure-call-count=1 \
--inner-function-line-count=1 \
--loop-count=5"
readonly MEDIUM_OPTS="\
--closure-count=50 \
--function-count=50 \
--inner-function-count=20 \
--function-call-count=5 \
--closure-call-count=5 \
--inner-function-line-count=2 \
--loop-count=5"
readonly HEAVY_OPTS="\
--closure-count=200 \
--function-count=200 \
--inner-function-count=40 \
--function-call-count=10 \
--closure-call-count=10 \
--inner-function-line-count=3 \
--loop-count=5"
function generate {
local generator="./second_batch_js_generator.py"
local header="// Generated with $generator $@"
{
echo $header;
$generator $@ | yui-compressor --type js;
}
}
generate $LIGHT_OPTS > second_batch_js_light.min.js
generate $MEDIUM_OPTS > second_batch_js_medium.min.js
generate $HEAVY_OPTS > second_batch_js_heavy.min.js
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Second batch JS</title>
</head>
<style>
#spinner {
width: 600px;
height: 10px;
border-right: black;
position: relative;
background: repeating-linear-gradient(
-45deg,
orange,
orange 21px,
yellow 21px,
yellow 42px
);
}
#spinner-container {
width: 300px;
height: 10px;
overflow: hidden;
border: solid thin darkorange;
border-radius: 4px;
margin-top: 50px;
}
.spinner-loaded #spinner {
background: repeating-linear-gradient(
-45deg,
steelblue,
steelblue 21px,
aqua 21px,
aqua 42px
);
}
#spinner-container.spinner-loaded {
border: solid thin steelblue;
}
input {
font-size: 150%;
width: 302px;
margin-top: 30px;
margin-bottom: 30px;
}
</style>
<center>
<div id="spinner-container">
<div id="spinner"></div>
</div>
<input id="load" type="button" value="Start loading" onclick="kickOffLoading()"></input>
<input id="run" style='display: none' type="button" value="Click me!" onclick="onRunClick()"></input>
<p id="results"></p>
<p>Note: running this test interactively may activate compositor
prioritization during loading, which may skew the results.</p>
</center>
<script>
// Flag that indicates the test is ready to begin.
window.__ready = false;
// Flag that indicates the test has finished executing.
window.__finished = false;
var results = document.getElementById('results');
function kickOffLoading() {
var loadButton = document.getElementById('load');
loadButton.disabled = true;
var variant =
location.search.length > 0 ? location.search.substr(1) : 'medium';
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript')
script.setAttribute('src', 'second_batch_js_' + variant + '.min.js')
script.addEventListener('load', onLoadComplete);
document.body.appendChild(script);
}
function onLoadComplete() {
var loadButton = document.getElementById('load');
var runButton = document.getElementById('run');
loadButton.style.display = 'none';
runButton.style.display = 'block';
spinnerContainer.classList.add('spinner-loaded');
window.__ready = true;
}
function onRunClick() {
results.innerText = 'Your lucky number is: ' + main(1);
window.requestAnimationFrame(finishTest);
}
function finishTest() {
window.__finished = true;
}
// Perform main thread animation during the benchmark to gauge main thread
// responsiveness.
var spinner = document.getElementById('spinner');
var spinnerContainer = document.getElementById('spinner-container');
function animateSpinner(timestamp) {
var width = parseInt(window.getComputedStyle(spinnerContainer).width);
var x = -(timestamp / 8) % width;
spinner.style.left = x + 'px';
window.requestAnimationFrame(animateSpinner);
}
window.requestAnimationFrame(animateSpinner);
</script>
</html>
#!/usr/bin/env python
# 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.
from __future__ import print_function
import argparse
import StringIO
import random
import sys
import zlib
# Generates synthetic Javascript for measuring the speed of parsing,
# compilation and initial execution.
# - top-level closure count
# - top-level function count
# - inner function count
# - size of code in inner functions
# - number of closures to call
# - number of top-level functions to call
# - loop count
def _ParseArguments():
parser = argparse.ArgumentParser(
description='Synthetic Javascript generator')
parser.add_argument('--closure-count', metavar='N', type=int, default=1,
help='Number of top-level closures to generate')
parser.add_argument('--function-count', metavar='N', type=int, default=1,
help='Number of top-level functions to generate')
parser.add_argument('--inner-function-count', metavar='N', type=int,
default=1, help='Number of inner functions to generate')
parser.add_argument('--inner-function-line-count', metavar='N', type=int,
default=1, help='Lines of code in each inner function')
parser.add_argument('--closure-call-count', metavar='N', type=int,
default=1, help='Number of top-level closures to call')
parser.add_argument('--function-call-count', metavar='N', type=int,
default=1, help='Number of top-level functions to call')
parser.add_argument('--loop-count', metavar='N', type=int,
default=1, help='Number of top-level loop iterations')
return parser.parse_args()
def _CreateRandomGeneratorForKey(key):
return random.Random(zlib.crc32(key))
def _GenerateLeafFunction(out, name, line_count, indent=0):
operations = [
'value += 1',
'value -= 2',
'value *= 3',
'value /= 4',
'value = Math.sin(value)',
'value = Math.pow(value, 2)',
]
indent = ' ' * indent
rand = _CreateRandomGeneratorForKey(name)
print(indent + 'function %s(value) {' % name, file=out)
for _ in xrange(line_count):
print(indent + ' %s;' % rand.choice(operations), file=out)
print(indent + ' return value;', file=out)
print(indent + '}\n', file=out)
def _ClosureInnerFunctionName(closure_index, inner_index):
return 'closure%dInnerFunction%d' % (closure_index, inner_index)
def _TopLevelClosureEntryPoint(closure_index):
return 'closure%d' % (closure_index)
def _GenerateTopLevelClosures(
out, count, inner_function_count, inner_function_line_count):
for closure_index in xrange(count):
print('(function() { // closure %d' % closure_index, file=out)
for inner_index in xrange(inner_function_count):
_GenerateLeafFunction(
out,
_ClosureInnerFunctionName(closure_index, inner_index),
inner_function_line_count,
indent=1)
print('window.%s = function(value) {' %
_TopLevelClosureEntryPoint(closure_index), file=out)
for inner_index in xrange(inner_function_count):
print(' value = %s(value);' %
_ClosureInnerFunctionName(closure_index, inner_index), file=out)
print(' return value;', file=out)
print('}', file=out)
print('})(); // closure %d\n' % closure_index, file=out)
def _FunctionInnerFunctionName(function_index, inner_index):
return 'function%dInnerFunction%d' % (function_index, inner_index)
def _TopLevelFunctionEntryPoint(function_index):
return 'function%d' % (function_index)
def _GenerateTopLevelFunctions(
out, count, inner_function_count, inner_function_line_count):
for function_index in xrange(count):
for inner_index in xrange(inner_function_count / 2):
_GenerateLeafFunction(
out,
_FunctionInnerFunctionName(function_index, inner_index),
inner_function_line_count)
print('function %s(value) {' %
_TopLevelFunctionEntryPoint(function_index), file=out)
for inner_index in xrange(inner_function_count / 2, inner_function_count):
_GenerateLeafFunction(
out,
_FunctionInnerFunctionName(function_index, inner_index),
inner_function_line_count,
indent=1)
for inner_index in xrange(inner_function_count):
print(' value = %s(value);' %
_FunctionInnerFunctionName(function_index, inner_index), file=out)
print(' return value;', file=out)
print('}\n', file=out)
def _GenerateMain(out, loop_count, closure_call_count, function_call_count):
print('function main(value) {', file=out)
for _ in xrange(loop_count):
for i in xrange(closure_call_count):
print(' value = %s(value);' % _TopLevelClosureEntryPoint(i), file=out)
for i in xrange(function_call_count):
print(' value = %s(value);' % _TopLevelFunctionEntryPoint(i), file=out)
print(' return value;', file=out)
print('}\n', file=out)
def Main():
args = _ParseArguments()
out = StringIO.StringIO()
print('// WARNING: Generated source code. Do not edit.', file=out)
print('//', file=out)
print('// This file was generated with the following options:', file=out)
print('// %s' % ' '.join(sys.argv), file=out)
print(file=out)
_GenerateTopLevelClosures(
out,
args.closure_count,
args.inner_function_count,
args.inner_function_line_count)
_GenerateTopLevelFunctions(
out,
args.function_count,
args.inner_function_count,
args.inner_function_line_count)
_GenerateMain(
out,
args.loop_count,
args.closure_call_count,
args.function_call_count)
print(out.getvalue())
if __name__ == '__main__':
sys.exit(Main())
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment