util: improve format performance
PR-URL: https://github.com/nodejs/node/pull/15422 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
This commit is contained in:
parent
6f340762d8
commit
faaefa8082
@ -2,35 +2,30 @@
|
|||||||
|
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
const common = require('../common');
|
const common = require('../common');
|
||||||
const types = [
|
|
||||||
'string',
|
|
||||||
'number',
|
|
||||||
'object',
|
|
||||||
'unknown',
|
|
||||||
'no-replace'
|
|
||||||
];
|
|
||||||
const bench = common.createBenchmark(main, {
|
|
||||||
n: [2e6],
|
|
||||||
type: types
|
|
||||||
});
|
|
||||||
|
|
||||||
const inputs = {
|
const inputs = {
|
||||||
'string': ['Hello, my name is %s', 'fred'],
|
'string': ['Hello, my name is %s', 'Fred'],
|
||||||
'number': ['Hi, I was born in %d', 1942],
|
'string-2': ['Hello, %s is my name', 'Fred'],
|
||||||
'object': ['An error occurred %j', { msg: 'This is an error', code: 'ERR' }],
|
'number': ['Hi, I was born in %d', 1989],
|
||||||
|
'replace-object': ['An error occurred %j', { msg: 'This is an error' }],
|
||||||
'unknown': ['hello %a', 'test'],
|
'unknown': ['hello %a', 'test'],
|
||||||
'no-replace': [1, 2]
|
'no-replace': [1, 2],
|
||||||
|
'no-replace-2': ['foobar', 'yeah', 'mensch', 5],
|
||||||
|
'only-objects': [{ msg: 'This is an error' }, { msg: 'This is an error' }],
|
||||||
|
'many-%': ['replace%%%%s%%%%many%s%s%s', 'percent'],
|
||||||
};
|
};
|
||||||
|
|
||||||
function main(conf) {
|
const bench = common.createBenchmark(main, {
|
||||||
const n = conf.n | 0;
|
n: [4e6],
|
||||||
const type = conf.type;
|
type: Object.keys(inputs)
|
||||||
|
});
|
||||||
|
|
||||||
const input = inputs[type];
|
function main({ n, type }) {
|
||||||
|
const [first, second] = inputs[type];
|
||||||
|
|
||||||
bench.start();
|
bench.start();
|
||||||
for (var i = 0; i < n; i++) {
|
for (var i = 0; i < n; i++) {
|
||||||
util.format(input[0], input[1]);
|
util.format(first, second);
|
||||||
}
|
}
|
||||||
bench.end(n);
|
bench.end(n);
|
||||||
}
|
}
|
||||||
|
72
lib/util.js
72
lib/util.js
@ -177,12 +177,16 @@ function tryStringify(arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function format(f) {
|
function format(f) {
|
||||||
|
var i, tempStr;
|
||||||
if (typeof f !== 'string') {
|
if (typeof f !== 'string') {
|
||||||
const objects = new Array(arguments.length);
|
if (arguments.length === 0) return '';
|
||||||
for (var index = 0; index < arguments.length; index++) {
|
var res = '';
|
||||||
objects[index] = inspect(arguments[index]);
|
for (i = 0; i < arguments.length - 1; i++) {
|
||||||
|
res += inspect(arguments[i]);
|
||||||
|
res += ' ';
|
||||||
}
|
}
|
||||||
return objects.join(' ');
|
res += inspect(arguments[i]);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments.length === 1) return f;
|
if (arguments.length === 1) return f;
|
||||||
@ -190,49 +194,49 @@ function format(f) {
|
|||||||
var str = '';
|
var str = '';
|
||||||
var a = 1;
|
var a = 1;
|
||||||
var lastPos = 0;
|
var lastPos = 0;
|
||||||
for (var i = 0; i < f.length;) {
|
for (i = 0; i < f.length - 1; i++) {
|
||||||
if (f.charCodeAt(i) === 37/*'%'*/ && i + 1 < f.length) {
|
if (f.charCodeAt(i) === 37) { // '%'
|
||||||
if (f.charCodeAt(i + 1) !== 37/*'%'*/ && a >= arguments.length) {
|
const nextChar = f.charCodeAt(++i);
|
||||||
++i;
|
if (a !== arguments.length) {
|
||||||
continue;
|
switch (nextChar) {
|
||||||
}
|
case 115: // 's'
|
||||||
if (lastPos < i)
|
tempStr = String(arguments[a++]);
|
||||||
str += f.slice(lastPos, i);
|
|
||||||
switch (f.charCodeAt(i + 1)) {
|
|
||||||
case 100: // 'd'
|
|
||||||
str += Number(arguments[a++]);
|
|
||||||
break;
|
|
||||||
case 105: // 'i'
|
|
||||||
str += parseInt(arguments[a++]);
|
|
||||||
break;
|
|
||||||
case 102: // 'f'
|
|
||||||
str += parseFloat(arguments[a++]);
|
|
||||||
break;
|
break;
|
||||||
case 106: // 'j'
|
case 106: // 'j'
|
||||||
str += tryStringify(arguments[a++]);
|
tempStr = tryStringify(arguments[a++]);
|
||||||
break;
|
break;
|
||||||
case 115: // 's'
|
case 100: // 'd'
|
||||||
str += String(arguments[a++]);
|
tempStr = `${Number(arguments[a++])}`;
|
||||||
break;
|
break;
|
||||||
case 79: // 'O'
|
case 79: // 'O'
|
||||||
str += inspect(arguments[a++]);
|
tempStr = inspect(arguments[a++]);
|
||||||
break;
|
break;
|
||||||
case 111: // 'o'
|
case 111: // 'o'
|
||||||
str += inspect(arguments[a++],
|
tempStr = inspect(arguments[a++],
|
||||||
{ showHidden: true, depth: 4, showProxy: true });
|
{ showHidden: true, depth: 4, showProxy: true });
|
||||||
break;
|
break;
|
||||||
case 37: // '%'
|
case 105: // 'i'
|
||||||
str += '%';
|
tempStr = `${parseInt(arguments[a++])}`;
|
||||||
break;
|
break;
|
||||||
|
case 102: // 'f'
|
||||||
|
tempStr = `${parseFloat(arguments[a++])}`;
|
||||||
|
break;
|
||||||
|
case 37: // '%'
|
||||||
|
str += f.slice(lastPos, i);
|
||||||
|
lastPos = i + 1;
|
||||||
|
continue;
|
||||||
default: // any other character is not a correct placeholder
|
default: // any other character is not a correct placeholder
|
||||||
str += '%';
|
|
||||||
lastPos = i = i + 1;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
lastPos = i = i + 2;
|
if (lastPos !== i - 1)
|
||||||
continue;
|
str += f.slice(lastPos, i - 1);
|
||||||
|
str += tempStr;
|
||||||
|
lastPos = i + 1;
|
||||||
|
} else if (nextChar === 37) {
|
||||||
|
str += f.slice(lastPos, i);
|
||||||
|
lastPos = i + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
if (lastPos === 0)
|
if (lastPos === 0)
|
||||||
str = f;
|
str = f;
|
||||||
@ -240,7 +244,7 @@ function format(f) {
|
|||||||
str += f.slice(lastPos);
|
str += f.slice(lastPos);
|
||||||
while (a < arguments.length) {
|
while (a < arguments.length) {
|
||||||
const x = arguments[a++];
|
const x = arguments[a++];
|
||||||
if (x === null || (typeof x !== 'object' && typeof x !== 'symbol')) {
|
if ((typeof x !== 'object' && typeof x !== 'symbol') || x === null) {
|
||||||
str += ` ${x}`;
|
str += ` ${x}`;
|
||||||
} else {
|
} else {
|
||||||
str += ` ${inspect(x)}`;
|
str += ` ${inspect(x)}`;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user