react/scripts/bench/measure.py

152 lines
4.6 KiB
Python
Executable File

#!/usr/bin/env python
# Copyright 2015-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
import functools
import json
import os
import subprocess
import sys
def _run_js_in_jsc(jit, js, env):
return subprocess.check_call(
['jsc', '-e', """
function now() {
return preciseTime() * 1000;
}
function globalEval(code) {
(0, eval)(code);
}
function report(label, time) {
print(label + '_' + %(engine)s, time);
}
this.ENV = %(env)s;
%(js)s
""" % {
'env': json.dumps(env),
'js': js,
'engine': json.dumps('jsc_' + ('jit' if jit else 'nojit')),
}],
env=dict(os.environ, JSC_useJIT='yes' if jit else 'no'),
)
_run_js_in_jsc_jit = functools.partial(_run_js_in_jsc, True)
_run_js_in_jsc_nojit = functools.partial(_run_js_in_jsc, False)
def _run_js_in_node(js, env):
return subprocess.check_call(
['node', '-e', """
function now() {
var hrTime = process.hrtime();
return hrTime[0] * 1e3 + hrTime[1] * 1e-6;
}
function globalEval(code) {
var vm = require('vm');
// Hide "module" so UMD wrappers use the global
vm.runInThisContext('(function(module){' + code + '\\n})()');
}
function readFile(filename) {
var fs = require('fs');
return fs.readFileSync(filename);
}
function report(label, time) {
console.log(label + '_node', time);
}
global.ENV = %(env)s;
%(js)s
""" % {
'env': json.dumps(env),
'js': js
}]
)
def _measure_ssr_ms(engine, react_path, bench_name, bench_path, measure_warm):
engine(
"""
var reactCode = readFile(ENV.react_path);
var START = now();
globalEval(reactCode);
var END = now();
if (typeof React !== 'object') throw new Error('React not laoded');
report('factory_ms', END - START);
globalEval(readFile(ENV.bench_path));
if (typeof Benchmark !== 'function') {
throw new Error('benchmark not loaded');
}
var START = now();
var html = React.renderToString(React.createElement(Benchmark));
html.charCodeAt(0); // flatten ropes
var END = now();
report('ssr_' + ENV.bench_name + '_cold_ms', END - START);
var warmup = ENV.measure_warm ? 80 : 0;
var trials = ENV.measure_warm ? 40 : 0;
for (var i = 0; i < warmup; i++) {
React.renderToString(React.createElement(Benchmark));
}
for (var i = 0; i < trials; i++) {
var START = now();
var html = React.renderToString(React.createElement(Benchmark));
html.charCodeAt(0); // flatten ropes
var END = now();
report('ssr_' + ENV.bench_name + '_warm_ms', END - START);
}
""",
{
'bench_name': bench_name,
'bench_path': bench_path,
'measure_warm': measure_warm,
'react_path': react_path,
},
)
def _main():
if len(sys.argv) != 2:
sys.stderr.write("usage: measure.py react.min.js >out.txt\n")
return 1
react_path = sys.argv[1]
trials = 30
sys.stderr.write("Measuring SSR for PE benchmark (%d trials)\n" % trials)
for i in range(trials):
for engine in [
_run_js_in_jsc_jit,
_run_js_in_jsc_nojit,
_run_js_in_node
]:
_measure_ssr_ms(engine, react_path, 'pe', 'bench-pe-es5.js', False)
sys.stderr.write(".")
sys.stderr.flush()
sys.stderr.write("\n")
trials = 3
sys.stderr.write("Measuring SSR for PE with warm JIT (%d slow trials)\n" % trials)
for i in range(trials):
for engine in [
_run_js_in_jsc_jit,
_run_js_in_jsc_nojit,
_run_js_in_node
]:
_measure_ssr_ms(engine, react_path, 'pe', 'bench-pe-es5.js', True)
sys.stderr.write(".")
sys.stderr.flush()
sys.stderr.write("\n")
if __name__ == '__main__':
sys.exit(_main())