From 0e5308991a3afe60ba25ff7efc3167803cfed5aa Mon Sep 17 00:00:00 2001 From: tsctx <91457664+tsctx@users.noreply.github.com> Date: Sat, 24 Feb 2024 18:20:12 +0900 Subject: [PATCH] refactor: remove sort logic --- benchmarks/sort.mjs | 50 ----------- lib/web/fetch/headers.js | 3 +- lib/web/fetch/sort.js | 187 --------------------------------------- test/fetch/sort.js | 90 ------------------- 4 files changed, 1 insertion(+), 329 deletions(-) delete mode 100644 benchmarks/sort.mjs delete mode 100644 lib/web/fetch/sort.js delete mode 100644 test/fetch/sort.js diff --git a/benchmarks/sort.mjs b/benchmarks/sort.mjs deleted file mode 100644 index bc5d2bc71ed..00000000000 --- a/benchmarks/sort.mjs +++ /dev/null @@ -1,50 +0,0 @@ -import { bench, group, run } from 'mitata' -import { sort, heapSort, introSort } from '../lib/web/fetch/sort.js' - -function compare (a, b) { - return a < b ? -1 : 1 -} - -const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' -const charactersLength = characters.length - -function generateAsciiString (length) { - let result = '' - for (let i = 0; i < length; ++i) { - result += characters[Math.floor(Math.random() * charactersLength)] - } - return result -} - -const settings = { - tiny: 32, - small: 64, - middle: 128, - large: 512 -} - -for (const [name, length] of Object.entries(settings)) { - group(`sort (${name})`, () => { - const array = Array.from(new Array(length), () => generateAsciiString(12)) - // sort(array, compare) - bench('Array#sort', () => array.slice().sort(compare)) - bench('sort (intro sort)', () => sort(array.slice(), compare)) - - // sort(array, start, end, compare) - bench('intro sort', () => introSort(array.slice(), 0, array.length, compare)) - bench('heap sort', () => heapSort(array.slice(), 0, array.length, compare)) - }) - - group(`sort sortedArray (${name})`, () => { - const array = Array.from(new Array(length), () => generateAsciiString(12)).sort(compare) - // sort(array, compare) - bench('Array#sort', () => array.sort(compare)) - bench('sort (intro sort)', () => sort(array, compare)) - - // sort(array, start, end, compare) - bench('intro sort', () => introSort(array, 0, array.length, compare)) - bench('heap sort', () => heapSort(array, 0, array.length, compare)) - }) -} - -await run() diff --git a/lib/web/fetch/headers.js b/lib/web/fetch/headers.js index bdb53b52654..f21c33b438d 100644 --- a/lib/web/fetch/headers.js +++ b/lib/web/fetch/headers.js @@ -12,7 +12,6 @@ const { } = require('./util') const { webidl } = require('./webidl') const assert = require('node:assert') -const { sort } = require('./sort') const kHeadersMap = Symbol('headers map') const kHeadersSortedMap = Symbol('headers map sorted') @@ -328,7 +327,7 @@ class HeadersList { // 3.2.2. Assert: value is non-null. assert(value !== null) } - return sort(array, compareHeaderName) + return array.sort(compareHeaderName) } } } diff --git a/lib/web/fetch/sort.js b/lib/web/fetch/sort.js deleted file mode 100644 index 230f2e2645c..00000000000 --- a/lib/web/fetch/sort.js +++ /dev/null @@ -1,187 +0,0 @@ -'use strict' - -/** **binary insertion sort** - * - Best -> O(n) - * - Average -> O(n^2) - * - Worst -> O(n^2) - * - Memory -> O(n) total, O(1) auxiliary - * - Stable -> true - * @param {any[]} array - * @param {number} begin begin - * @param {number} end end - * @param {(a: any, b: any) => number} compare - */ -function binaryInsertionSort (array, begin, end, compare) { - for ( - let i = begin + 1, j = 0, right = 0, left = 0, pivot = 0, x; - i < end; - ++i - ) { - x = array[i] - left = 0 - right = i - // binary search - while (left < right) { - // middle index - pivot = left + ((right - left) >> 1) - if (compare(array[pivot], x) <= 0) { - left = pivot + 1 - } else { - right = pivot - } - } - if (i !== pivot) { - j = i - while (j > left) { - array[j] = array[--j] - } - array[left] = x - } - } - return array -} - -/** - * @param {number} num - */ -function log2 (num) { - // Math.floor(Math.log2(num)) - let log = 0 - // eslint-disable-next-line no-cond-assign - while ((num >>= 1)) ++log - return log -} - -/** **intro sort** - * - Average -> O(n log n) - * - Worst -> O(n log n) - * - Stable -> false - * @param {any[]} array - * @param {number} begin begin - * @param {number} end end - * @param {(a: any, b: any) => number} compare - */ -function introSort (array, begin, end, compare) { - return _introSort(array, begin, end, log2(end - begin) << 1, compare) -} - -/** - * @param {any[]} array - * @param {number} begin - * @param {number} end - * @param {number} depth - * @param {(a: any, b: any) => number} compare - */ -function _introSort (array, begin, end, depth, compare) { - if (end - begin <= 32) { - return binaryInsertionSort(array, begin, end, compare) - } - if (depth-- <= 0) { - return heapSort(array, begin, end, compare) - } - // median of three quick sort - let i = begin - let j = end - 1 - const pivot = medianOf3( - array[i], - array[i + ((j - i) >> 1)], - array[j], - compare - ) - let firstPass = true - while (true) { - while (compare(array[i], pivot) < 0) ++i - while (compare(pivot, array[j]) < 0) --j - if (i >= j) break; - [array[i], array[j]] = [array[j], array[i]] - ++i - --j - firstPass = false - } - if (i - begin > 1 && !firstPass) _introSort(array, begin, i, depth, compare) - // if (end - (j + 1) > 1) ... - if (end - j > 2 && !firstPass) _introSort(array, j + 1, end, depth, compare) - return array -} - -/** **heap sort (bottom up)** - * - Best -> Ω(n) - * - Average -> O(n log n) - * - Worst -> O(n log n) - * - Memory -> O(n) total, O(1) auxiliary - * - Stable -> false - * @param {any[]} array - * @param {number} begin - * @param {number} end - * @param {(a: any, b: any) => number} compare - */ -function heapSort (array, begin, end, compare) { - const N = end - begin - let p = N >> 1 - let q = N - 1 - let x - while (p > 0) { - downHeap(array, array[begin + p - 1], begin, --p, q, compare) - } - while (q > 0) { - x = array[begin + q] - array[begin + q] = array[begin] - downHeap(array, (array[begin] = x), begin, 0, --q, compare) - } - return array -} - -/** - * @param {any[]} array - * @param {any} x - * @param {number} begin - * @param {number} p - * @param {number} q - * @param {(a: any, b: any) => number} compare - */ -function downHeap (array, x, begin, p, q, compare) { - let c - while ((c = (p << 1) + 1) <= q) { - if (c < q && compare(array[begin + c], array[begin + c + 1]) < 0) ++c - if (compare(x, array[begin + c]) >= 0) break - array[begin + p] = array[begin + c] - p = c - } - array[begin + p] = x -} - -/** - * @param {any} x - * @param {any} y - * @param {any} z - * @param {(a: any, b: any) => number} compare - */ -function medianOf3 (x, y, z, compare) { - return compare(x, y) < 0 - ? compare(y, z) < 0 - ? y - : compare(z, x) < 0 - ? x - : z - : compare(z, y) < 0 - ? y - : compare(x, z) < 0 - ? x - : z -} - -/** - * @param {any[]} array - * @param {(a: any, b: any) => number} compare - */ -function sort (array, compare) { - const length = array.length - return _introSort(array, 0, length, log2(length) << 1, compare) -} - -module.exports = { - sort, - binaryInsertionSort, - introSort, - heapSort -} diff --git a/test/fetch/sort.js b/test/fetch/sort.js deleted file mode 100644 index b2eef9ca699..00000000000 --- a/test/fetch/sort.js +++ /dev/null @@ -1,90 +0,0 @@ -'use strict' - -const { describe, test } = require('node:test') -const assert = require('node:assert') -const { sort, heapSort, binaryInsertionSort, introSort } = require('../../lib/web/fetch/sort') - -function generateRandomNumberArray (length) { - const array = new Uint16Array(length) - for (let i = 0; i < length; ++i) { - array[i] = (65535 * Math.random()) | 0 - } - return array -} - -const compare = (a, b) => a - b - -const SORT_RUN = 4000 - -const SORT_ELEMENT = 200 - -describe('sort', () => { - const arrays = new Array(SORT_RUN) - const expectedArrays = new Array(SORT_RUN) - - for (let i = 0; i < SORT_RUN; ++i) { - const array = generateRandomNumberArray(SORT_ELEMENT) - const expected = array.slice().sort(compare) - arrays[i] = array - expectedArrays[i] = expected - } - - test('binary insertion sort', () => { - for (let i = 0; i < SORT_RUN; ++i) { - assert.deepStrictEqual(binaryInsertionSort(arrays[i].slice(), 0, SORT_ELEMENT, compare), expectedArrays[i]) - } - }) - - test('heap sort', () => { - for (let i = 0; i < SORT_RUN; ++i) { - assert.deepStrictEqual(heapSort(arrays[i].slice(), 0, SORT_ELEMENT, compare), expectedArrays[i]) - } - }) - - test('intro sort', () => { - for (let i = 0; i < SORT_RUN; ++i) { - assert.deepStrictEqual(introSort(arrays[i].slice(), 0, SORT_ELEMENT, compare), expectedArrays[i]) - } - }) - - test('sort', () => { - for (let i = 0; i < SORT_RUN; ++i) { - assert.deepStrictEqual(sort(arrays[i].slice(), compare), expectedArrays[i]) - } - }) -}) - -describe('sorted', () => { - const arrays = new Array(SORT_RUN) - const expectedArrays = new Array(SORT_RUN) - - for (let i = 0; i < SORT_RUN; ++i) { - const array = generateRandomNumberArray(SORT_ELEMENT).sort(compare) - arrays[i] = array - expectedArrays[i] = array.slice() - } - - test('binary insertion sort', () => { - for (let i = 0; i < SORT_RUN; ++i) { - assert.deepStrictEqual(binaryInsertionSort(arrays[i].slice(), 0, SORT_ELEMENT, compare), expectedArrays[i]) - } - }) - - test('heap sort', () => { - for (let i = 0; i < SORT_RUN; ++i) { - assert.deepStrictEqual(heapSort(arrays[i].slice(), 0, SORT_ELEMENT, compare), expectedArrays[i]) - } - }) - - test('intro sort', () => { - for (let i = 0; i < SORT_RUN; ++i) { - assert.deepStrictEqual(introSort(arrays[i].slice(), 0, SORT_ELEMENT, compare), expectedArrays[i]) - } - }) - - test('sort', () => { - for (let i = 0; i < SORT_RUN; ++i) { - assert.deepStrictEqual(sort(arrays[i].slice(), compare), expectedArrays[i]) - } - }) -})