Repository: nodejs/node
Pull request: url: remove array.reduce usage to make inspect faster

branch:

```sh
url/url-searchparams-inspect.js
url/url-searchparams-inspect.js n=100000 kind="params" variant="empty": 4,532,381.098194127
url/url-searchparams-inspect.js n=100000 kind="iterator-keys" variant="empty": 1,515,353.3785894632
url/url-searchparams-inspect.js n=100000 kind="iterator-values" variant="empty": 1,492,998.7614679476
url/url-searchparams-inspect.js n=100000 kind="iterator-entries" variant="empty": 1,450,254.4522195323
url/url-searchparams-inspect.js n=100000 kind="params" variant="small": 403,675.9409357187
url/url-searchparams-inspect.js n=100000 kind="iterator-keys" variant="small": 427,352.2536421096
url/url-searchparams-inspect.js n=100000 kind="iterator-values" variant="small": 420,388.7130120308
url/url-searchparams-inspect.js n=100000 kind="iterator-entries" variant="small": 207,149.16684729385
url/url-searchparams-inspect.js n=100000 kind="params" variant="medium": 78,324.92739345282
url/url-searchparams-inspect.js n=100000 kind="iterator-keys" variant="medium": 103,255.19317270137
url/url-searchparams-inspect.js n=100000 kind="iterator-values" variant="medium": 105,868.77834677565
url/url-searchparams-inspect.js n=100000 kind="iterator-entries" variant="medium": 42,676.903041653466
url/url-searchparams-inspect.js n=100000 kind="params" variant="large": 10,407.476332765786
url/url-searchparams-inspect.js n=100000 kind="iterator-keys" variant="large": 15,924.216229468899
url/url-searchparams-inspect.js n=100000 kind="iterator-values" variant="large": 15,842.239285517238
url/url-searchparams-inspect.js n=100000 kind="iterator-entries" variant="large": 6,287.244407894947
```

main:

```sh
url/url-searchparams-inspect.js
url/url-searchparams-inspect.js n=100000 kind="params" variant="empty": 4,141,001.0870127855
url/url-searchparams-inspect.js n=100000 kind="iterator-keys" variant="empty": 1,456,942.7876779065
url/url-searchparams-inspect.js n=100000 kind="iterator-values" variant="empty": 975,149.1432105592
url/url-searchparams-inspect.js n=100000 kind="iterator-entries" variant="empty": 1,385,660.492394456
url/url-searchparams-inspect.js n=100000 kind="params" variant="small": 382,729.5216981326
url/url-searchparams-inspect.js n=100000 kind="iterator-keys" variant="small": 402,301.29698277207
url/url-searchparams-inspect.js n=100000 kind="iterator-values" variant="small": 403,590.5432681854
url/url-searchparams-inspect.js n=100000 kind="iterator-entries" variant="small": 197,061.3393303881
url/url-searchparams-inspect.js n=100000 kind="params" variant="medium": 78,651.96299050128
url/url-searchparams-inspect.js n=100000 kind="iterator-keys" variant="medium": 101,996.0845906241
url/url-searchparams-inspect.js n=100000 kind="iterator-values" variant="medium": 101,739.53835371115
url/url-searchparams-inspect.js n=100000 kind="iterator-entries" variant="medium": 41,671.14631489552
url/url-searchparams-inspect.js n=100000 kind="params" variant="large": 9,892.61944926823
url/url-searchparams-inspect.js n=100000 kind="iterator-keys" variant="large": 15,148.689404508617
url/url-searchparams-inspect.js n=100000 kind="iterator-values" variant="large": 15,377.710695515232
url/url-searchparams-inspect.js n=100000 kind="iterator-entries" variant="large": 5,952.288479327792
```

Reduce is slow, we should prefer iteration

Changed files:
filename: benchmark/url/url-searchparams-inspect.js
patch: @@ -0,0 +1,39 @@
+'use strict';
+const common = require('../common.js');
+const { inspect } = require('util');
+
+const bench = common.createBenchmark(main, {
+  variant: ['empty', 'small', 'medium', 'large'],
+  kind: ['params', 'iterator-keys', 'iterator-values', 'iterator-entries'],
+  n: [1e5],
+});
+
+function makeParams(size) {
+  const u = new URLSearchParams();
+  for (let i = 0; i < size; i++) {
+    u.append('k' + i, 'v' + i);
+  }
+  return u;
+}
+
+function main({ variant, kind, n }) {
+  const sizes = { empty: 0, small: 3, medium: 16, large: 128 };
+  const size = sizes[variant];
+  const params = makeParams(size);
+  let target;
+  if (kind === 'params') {
+    target = params;
+  } else if (kind === 'iterator-keys') {
+    target = params.keys();
+  } else if (kind === 'iterator-values') {
+    target = params.values();
+  } else {
+    target = params.entries();
+  }
+
+  bench.start();
+  for (let i = 0; i < n; i++) {
+    inspect(target, { showHidden: false, depth: 2 });
+  }
+  bench.end(n);
+}

filename: lib/internal/url.js
patch: @@ -6,8 +6,6 @@ const {
   ArrayPrototypeJoin,
   ArrayPrototypeMap,
   ArrayPrototypePush,
-  ArrayPrototypeReduce,
-  ArrayPrototypeSlice,
   Boolean,
   Int8Array,
   IteratorPrototype,
@@ -281,25 +279,19 @@ class URLSearchParamsIterator {
     }
     const index = this.#index;
     const values = getURLSearchParamsList(this.#target);
-    const output = ArrayPrototypeReduce(
-      ArrayPrototypeSlice(values, index),
-      (prev, cur, i) => {
-        const key = i % 2 === 0;
-        if (this.#kind === 'key' && key) {
-          ArrayPrototypePush(prev, cur);
-        } else if (this.#kind === 'value' && !key) {
-          ArrayPrototypePush(prev, cur);
-        } else if (this.#kind === 'key+value' && !key) {
-          ArrayPrototypePush(prev, [values[index + i - 1], cur]);
-        }
-        return prev;
-      },
-      [],
-    );
-    const breakLn = StringPrototypeIncludes(inspect(output, innerOpts), '\n');
+    const output = [];
+    for (let i = index; i < values.length; i++) {
+      const isKey = ((i - index) % 2) === 0;
+      if (this.#kind === 'key') {
+        if (isKey) ArrayPrototypePush(output, values[i]);
+      } else if (!isKey) {
+        ArrayPrototypePush(output, this.#kind === 'value' ? values[i] : [values[i - 1], values[i]]);
+      }
+    }
+    const hasBreak = StringPrototypeIncludes(inspect(output, innerOpts), '\n');
     const outputStrs = ArrayPrototypeMap(output, (p) => inspect(p, innerOpts));
     let outputStr;
-    if (breakLn) {
+    if (hasBreak) {
       outputStr = `\n  ${ArrayPrototypeJoin(outputStrs, ',\n  ')}`;
     } else {
       outputStr = ` ${ArrayPrototypeJoin(outputStrs, ', ')}`;
@@ -456,11 +448,10 @@ class URLSearchParams {
         output,
         `${innerInspect(list[i])} => ${innerInspect(list[i + 1])}`);
 
-    const length = ArrayPrototypeReduce(
-      output,
-      (prev, cur) => prev + removeColors(cur).length + separator.length,
-      -separator.length,
-    );
+    let length = -separator.length;
+    for (let i = 0; i < output.length; i++) {
+      length += removeColors(output[i]).length + separator.length;
+    }
     if (length > ctx.breakLength) {
       return `${this.constructor.name} {\n` +
       `  ${ArrayPrototypeJoin(output, ',\n  ')} }`;