From 33c242e7e98725e9cca7914186d6ca96eb9b1035 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Fri, 15 Apr 2016 13:13:49 -0700 Subject: console: refactor to use rest params and template strings Overall cleanup in code, eliminate reliance on `arguments`. Benchmarks show that as of v8 5.0.71.32, using rest params + apply has good performance. The spread operator is not yet well optimized in v8 ``` misc/console.js method=restAndSpread concat=1 n=1000000: 374779.38359 misc/console.js method=restAndSpread concat=0 n=1000000: 375988.30434 misc/console.js method=argumentsAndApply concat=1 n=1000000: 682618.61125 misc/console.js method=argumentsAndApply concat=0 n=1000000: 645093.74443 misc/console.js method=restAndApply concat=1 n=1000000: 682931.41217 misc/console.js method=restAndApply concat=0 n=1000000: 664473.09700 ``` PR-URL: https://github.com/nodejs/node/pull/6233 Reviewed-By: Brian White --- benchmark/misc/console.js | 133 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 benchmark/misc/console.js (limited to 'benchmark') diff --git a/benchmark/misc/console.js b/benchmark/misc/console.js new file mode 100644 index 0000000000..d352943e80 --- /dev/null +++ b/benchmark/misc/console.js @@ -0,0 +1,133 @@ +'use strict'; + +const common = require('../common.js'); +const assert = require('assert'); +const Writable = require('stream').Writable; +const util = require('util'); +const v8 = require('v8'); + +v8.setFlagsFromString('--allow_natives_syntax'); + +var bench = common.createBenchmark(main, { + method: ['restAndSpread', + 'argumentsAndApply', + 'restAndApply', + 'restAndConcat'], + concat: [1, 0], + n: [1000000] +}); + +const nullStream = createNullStream(); + +function usingRestAndConcat(...args) { + nullStream.write('this is ' + args[0] + ' of ' + args[1] + '\n'); +} + +function usingRestAndSpreadTS(...args) { + nullStream.write(`${util.format(...args)}\n`); +} + +function usingRestAndApplyTS(...args) { + nullStream.write(`${util.format.apply(null, args)}\n`); +} + +function usingArgumentsAndApplyTS() { + nullStream.write(`${util.format.apply(null, arguments)}\n`); +} + +function usingRestAndSpreadC(...args) { + nullStream.write(util.format(...args) + '\n'); +} + +function usingRestAndApplyC(...args) { + nullStream.write(util.format.apply(null, args) + '\n'); +} + +function usingArgumentsAndApplyC() { + nullStream.write(util.format.apply(null, arguments) + '\n'); +} + +function optimize(method, ...args) { + method(...args); + eval(`%OptimizeFunctionOnNextCall(${method.name})`); + method(...args); +} + +function runUsingRestAndConcat(n) { + optimize(usingRestAndConcat, 'a', 1); + + var i = 0; + bench.start(); + for (; i < n; i++) + usingRestAndConcat('a', 1); + bench.end(n); +} + +function runUsingRestAndSpread(n, concat) { + + const method = concat ? usingRestAndSpreadC : usingRestAndSpreadTS; + optimize(method, 'this is %s of %d', 'a', 1); + + var i = 0; + bench.start(); + for (; i < n; i++) + method('this is %s of %d', 'a', 1); + bench.end(n); +} + +function runUsingRestAndApply(n, concat) { + + const method = concat ? usingRestAndApplyC : usingRestAndApplyTS; + optimize(method, 'this is %s of %d', 'a', 1); + + var i = 0; + bench.start(); + for (; i < n; i++) + method('this is %s of %d', 'a', 1); + bench.end(n); +} + +function runUsingArgumentsAndApply(n, concat) { + + const method = concat ? usingArgumentsAndApplyC : usingArgumentsAndApplyTS; + optimize(method, 'this is %s of %d', 'a', 1); + + var i = 0; + bench.start(); + for (; i < n; i++) + method('this is %s of %d', 'a', 1); + bench.end(n); +} + +function main(conf) { + const n = +conf.n; + switch (conf.method) { + case 'restAndSpread': + runUsingRestAndSpread(n, conf.concat); + break; + case 'restAndApply': + runUsingRestAndApply(n, conf.concat); + break; + case 'argumentsAndApply': + runUsingArgumentsAndApply(n, conf.concat); + break; + case 'restAndConcat': + if (conf.concat) + runUsingRestAndConcat(n); + break; + default: + throw new Error('Unexpected method'); + } +} + +function createNullStream() { + // Used to approximate /dev/null + function NullStream() { + Writable.call(this, {}); + } + util.inherits(NullStream, Writable); + NullStream.prototype._write = function(cb) { + assert.strictEqual(cb.toString(), 'this is a of 1\n'); + }; + return new NullStream(); +} -- cgit v1.2.3