-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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: #6233 Reviewed-By: Brian White <mscdex@mscdex.net>
- Loading branch information
Showing
2 changed files
with
148 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters