Skip to content

Commit d0bf09d

Browse files
mscdexMyles Borins
authored and
Myles Borins
committed
util: improve format() performance further
Replacing the regexp and replace function with a loop improves performance by ~60-200%. PR-URL: #5360 Reviewed-By: James M Snell <[email protected]>
1 parent 72fb281 commit d0bf09d

File tree

1 file changed

+49
-24
lines changed

1 file changed

+49
-24
lines changed

lib/util.js

+49-24
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ function tryStringify(arg) {
1717
}
1818
}
1919

20-
const formatRegExp = /%[sdj%]/g;
2120
exports.format = function(f) {
2221
if (typeof f !== 'string') {
2322
const objects = new Array(arguments.length);
@@ -27,30 +26,56 @@ exports.format = function(f) {
2726
return objects.join(' ');
2827
}
2928

30-
if (arguments.length === 1) return f;
31-
32-
const len = arguments.length;
33-
const args = new Array(len);
34-
var i;
35-
for (i = 0; i < len; i++) {
36-
args[i] = arguments[i];
37-
}
38-
39-
i = 1;
40-
var str = f.replace(formatRegExp, function(x) {
41-
if (x === '%%') return '%';
42-
if (i >= len) return x;
43-
switch (x) {
44-
case '%s': return String(args[i++]);
45-
case '%d': return Number(args[i++]);
46-
case '%j': return tryStringify(args[i++]);
47-
// falls through
48-
default:
49-
return x;
29+
var argLen = arguments.length;
30+
31+
if (argLen === 1) return f;
32+
33+
var str = '';
34+
var a = 1;
35+
var lastPos = 0;
36+
for (var i = 0; i < f.length;) {
37+
if (f.charCodeAt(i) === 37/*'%'*/ && i + 1 < f.length) {
38+
switch (f.charCodeAt(i + 1)) {
39+
case 100: // 'd'
40+
if (a >= argLen)
41+
break;
42+
if (lastPos < i)
43+
str += f.slice(lastPos, i);
44+
str += Number(arguments[a++]);
45+
lastPos = i = i + 2;
46+
continue;
47+
case 106: // 'j'
48+
if (a >= argLen)
49+
break;
50+
if (lastPos < i)
51+
str += f.slice(lastPos, i);
52+
str += tryStringify(arguments[a++]);
53+
lastPos = i = i + 2;
54+
continue;
55+
case 115: // 's'
56+
if (a >= argLen)
57+
break;
58+
if (lastPos < i)
59+
str += f.slice(lastPos, i);
60+
str += String(arguments[a++]);
61+
lastPos = i = i + 2;
62+
continue;
63+
case 37: // '%'
64+
if (lastPos < i)
65+
str += f.slice(lastPos, i);
66+
str += '%';
67+
lastPos = i = i + 2;
68+
continue;
69+
}
5070
}
51-
});
52-
while (i < len) {
53-
const x = args[i++];
71+
++i;
72+
}
73+
if (lastPos === 0)
74+
str = f;
75+
else if (lastPos < f.length)
76+
str += f.slice(lastPos);
77+
while (a < argLen) {
78+
const x = arguments[a++];
5479
if (x === null || (typeof x !== 'object' && typeof x !== 'symbol')) {
5580
str += ' ' + x;
5681
} else {

0 commit comments

Comments
 (0)