mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
url: optimize URLSearchParams set/delete duplicate handling
PR-URL: https://github.com/nodejs/node/pull/62266 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Aviv Keller <me@aviv.sh>
This commit is contained in:
1 parent
44f9fc3643
commit
c20269679e
2 files changed
+78
-14
No files matched your search
@@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
const common = require('../common.js');
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
method: ['set', 'delete'],
|
||||
type: ['unique', 'duplicates'],
|
||||
count: [10, 1000],
|
||||
n: [1e4],
|
||||
});
|
||||
|
||||
function buildSeed(type, count) {
|
||||
const parts = new Array(count);
|
||||
|
||||
if (type === 'duplicates') {
|
||||
for (let i = 0; i < count; i++) {
|
||||
parts[i] = `dup=${i}`;
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < count; i++) {
|
||||
parts[i] = `k${i}=${i}`;
|
||||
}
|
||||
}
|
||||
|
||||
return new URLSearchParams(parts.join('&'));
|
||||
}
|
||||
|
||||
function main({ method, type, count, n }) {
|
||||
const seed = buildSeed(type, count);
|
||||
const key = type === 'duplicates' ? 'dup' : 'k0';
|
||||
const mutate = method === 'set' ?
|
||||
(params) => params.set(key, 'updated') :
|
||||
(params) => params.delete(key);
|
||||
|
||||
for (let i = 0; i < 1e3; i++) {
|
||||
mutate(new URLSearchParams(seed));
|
||||
}
|
||||
|
||||
bench.start();
|
||||
for (let i = 0; i < n; i++) {
|
||||
mutate(new URLSearchParams(seed));
|
||||
}
|
||||
bench.end(n);
|
||||
}
|
||||
+35
-14
@@ -495,26 +495,37 @@ class URLSearchParams {
|
||||
|
||||
const list = this.#searchParams;
|
||||
name = StringPrototypeToWellFormed(`${name}`);
|
||||
const { length } = list;
|
||||
let write = 0;
|
||||
|
||||
if (value !== undefined) {
|
||||
value = StringPrototypeToWellFormed(`${value}`);
|
||||
for (let i = 0; i < list.length;) {
|
||||
for (let i = 0; i < length; i += 2) {
|
||||
if (list[i] === name && list[i + 1] === value) {
|
||||
list.splice(i, 2);
|
||||
} else {
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
if (write !== i) {
|
||||
list[write] = list[i];
|
||||
list[write + 1] = list[i + 1];
|
||||
}
|
||||
write += 2;
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < list.length;) {
|
||||
for (let i = 0; i < length; i += 2) {
|
||||
if (list[i] === name) {
|
||||
list.splice(i, 2);
|
||||
} else {
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
if (write !== i) {
|
||||
list[write] = list[i];
|
||||
list[write + 1] = list[i + 1];
|
||||
}
|
||||
write += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (write !== length)
|
||||
list.length = write;
|
||||
|
||||
if (this.#context) {
|
||||
setURLSearchParamsModified(this.#context);
|
||||
}
|
||||
@@ -594,24 +605,34 @@ class URLSearchParams {
|
||||
const list = this.#searchParams;
|
||||
name = StringPrototypeToWellFormed(`${name}`);
|
||||
value = StringPrototypeToWellFormed(`${value}`);
|
||||
const { length } = list;
|
||||
|
||||
// If there are any name-value pairs whose name is `name`, in `list`, set
|
||||
// the value of the first such name-value pair to `value` and remove the
|
||||
// others.
|
||||
let found = false;
|
||||
for (let i = 0; i < list.length;) {
|
||||
let write = 0;
|
||||
for (let i = 0; i < length; i += 2) {
|
||||
const cur = list[i];
|
||||
let keep = true;
|
||||
if (cur === name) {
|
||||
if (!found) {
|
||||
list[i + 1] = value;
|
||||
list[write] = cur;
|
||||
list[write + 1] = value;
|
||||
found = true;
|
||||
i += 2;
|
||||
} else {
|
||||
list.splice(i, 2);
|
||||
keep = false;
|
||||
}
|
||||
} else {
|
||||
i += 2;
|
||||
} else if (write !== i) {
|
||||
list[write] = cur;
|
||||
list[write + 1] = list[i + 1];
|
||||
}
|
||||
if (keep)
|
||||
write += 2;
|
||||
}
|
||||
|
||||
if (found && write !== length) {
|
||||
list.length = write;
|
||||
}
|
||||
|
||||
// Otherwise, append a new name-value pair whose name is `name` and value
|
||||
|
||||
Reference in new issue
Block a user