mirror of https://github.com/nodejs/node.git
querystring: improve stringify() performance
PR-URL: https://github.com/nodejs/node/pull/33669 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>pull/33669/head
parent
76ceaff270
commit
7b46793eee
|
@ -3,7 +3,7 @@ const common = require('../common.js');
|
|||
const querystring = require('querystring');
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
type: ['noencode', 'encodemany', 'encodelast', 'array'],
|
||||
type: ['noencode', 'encodemany', 'encodelast', 'array', 'multiprimitives'],
|
||||
n: [1e6],
|
||||
});
|
||||
|
||||
|
@ -28,7 +28,12 @@ function main({ type, n }) {
|
|||
foo: [],
|
||||
baz: ['bar'],
|
||||
xyzzy: ['bar', 'quux', 'thud']
|
||||
}
|
||||
},
|
||||
multiprimitives: {
|
||||
foo: false,
|
||||
bar: -13.37,
|
||||
baz: '',
|
||||
},
|
||||
};
|
||||
const input = inputs[type];
|
||||
|
||||
|
|
|
@ -36,19 +36,25 @@ function encodeStr(str, noEscapeTable, hexTable) {
|
|||
|
||||
let out = '';
|
||||
let lastPos = 0;
|
||||
let i = 0;
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
outer:
|
||||
for (; i < len; i++) {
|
||||
let c = str.charCodeAt(i);
|
||||
|
||||
// ASCII
|
||||
if (c < 0x80) {
|
||||
if (noEscapeTable[c] === 1)
|
||||
continue;
|
||||
if (lastPos < i)
|
||||
out += str.slice(lastPos, i);
|
||||
lastPos = i + 1;
|
||||
out += hexTable[c];
|
||||
continue;
|
||||
while (c < 0x80) {
|
||||
if (noEscapeTable[c] !== 1) {
|
||||
if (lastPos < i)
|
||||
out += str.slice(lastPos, i);
|
||||
lastPos = i + 1;
|
||||
out += hexTable[c];
|
||||
}
|
||||
|
||||
if (++i === len)
|
||||
break outer;
|
||||
|
||||
c = str.charCodeAt(i);
|
||||
}
|
||||
|
||||
if (lastPos < i)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
const {
|
||||
Array,
|
||||
ArrayIsArray,
|
||||
MathAbs,
|
||||
ObjectCreate,
|
||||
ObjectKeys,
|
||||
} = primordials;
|
||||
|
@ -162,6 +163,25 @@ function stringifyPrimitive(v) {
|
|||
}
|
||||
|
||||
|
||||
function encodeStringified(v, encode) {
|
||||
if (typeof v === 'string')
|
||||
return (v.length ? encode(v) : '');
|
||||
if (typeof v === 'number' && isFinite(v)) {
|
||||
// Values >= 1e21 automatically switch to scientific notation which requires
|
||||
// escaping due to the inclusion of a '+' in the output
|
||||
return (MathAbs(v) < 1e21 ? '' + v : encode('' + v));
|
||||
}
|
||||
if (typeof v === 'boolean')
|
||||
return v ? 'true' : 'false';
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
function encodeStringifiedCustom(v, encode) {
|
||||
return encode(stringifyPrimitive(v));
|
||||
}
|
||||
|
||||
|
||||
function stringify(obj, sep, eq, options) {
|
||||
sep = sep || '&';
|
||||
eq = eq || '=';
|
||||
|
@ -170,6 +190,8 @@ function stringify(obj, sep, eq, options) {
|
|||
if (options && typeof options.encodeURIComponent === 'function') {
|
||||
encode = options.encodeURIComponent;
|
||||
}
|
||||
const convert =
|
||||
(encode === qsEscape ? encodeStringified : encodeStringifiedCustom);
|
||||
|
||||
if (obj !== null && typeof obj === 'object') {
|
||||
const keys = ObjectKeys(obj);
|
||||
|
@ -179,7 +201,7 @@ function stringify(obj, sep, eq, options) {
|
|||
for (let i = 0; i < len; ++i) {
|
||||
const k = keys[i];
|
||||
const v = obj[k];
|
||||
let ks = encode(stringifyPrimitive(k));
|
||||
let ks = convert(k, encode);
|
||||
ks += eq;
|
||||
|
||||
if (ArrayIsArray(v)) {
|
||||
|
@ -188,13 +210,13 @@ function stringify(obj, sep, eq, options) {
|
|||
const vlast = vlen - 1;
|
||||
for (let j = 0; j < vlen; ++j) {
|
||||
fields += ks;
|
||||
fields += encode(stringifyPrimitive(v[j]));
|
||||
fields += convert(v[j], encode);
|
||||
if (j < vlast)
|
||||
fields += sep;
|
||||
}
|
||||
} else {
|
||||
fields += ks;
|
||||
fields += encode(stringifyPrimitive(v));
|
||||
fields += convert(v, encode);
|
||||
}
|
||||
|
||||
if (i < flast)
|
||||
|
|
Loading…
Reference in New Issue