| #!/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 random |
| import StringIO |
| 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()) |