From 1575e5140ec315aaaa4928d0ca72be749fb3d4a6 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Fri, 13 Oct 2017 01:53:48 +0200 Subject: [PATCH] perf tests --- src/perf-tests/binary-search.ts | 45 ++++++++- src/perf-tests/sort.ts | 172 ++++++++++++++++++++++++++++++-- 2 files changed, 210 insertions(+), 7 deletions(-) diff --git a/src/perf-tests/binary-search.ts b/src/perf-tests/binary-search.ts index b1d63094f..b5d717e55 100644 --- a/src/perf-tests/binary-search.ts +++ b/src/perf-tests/binary-search.ts @@ -36,6 +36,11 @@ function setSearch(set: Set<number>, val: number) { return set.has(val); } +type Mask = { min: number, max: number, mask: ArrayLike<number> } +function maskSearch({ min, max, mask }: Mask, val: number) { + return val >= min && val <= max && !!mask[val - min]; +} + function prepare(list: ArrayLike<number>) { const obj = Object.create(null), set = new Set<number>(); for (let i = 0; i < list.length; i++) { @@ -66,6 +71,22 @@ function prepareObj(list: ArrayLike<number>) { return obj; } +function prepareMask(list: ArrayLike<number>): Mask { + let max = Number.NEGATIVE_INFINITY, min = Number.POSITIVE_INFINITY; + for (let i = 0; i < list.length; i++) { + const v = list[i]; + if (max < v) max = v; + if (min > v) min = v; + } + const mask = new Uint8Array(max - min + 1); + for (let i = 0; i < list.length; i++) { + const v = list[i]; + mask[v - min] = 1; + } + + return { min, max, mask }; +} + function testBinary(list: ArrayLike<number>, points: ArrayLike<number>) { let r = 0; for (let i = 0, _i = points.length; i < _i; i++) { @@ -90,21 +111,33 @@ function testSet(set: Set<number>, points: ArrayLike<number>) { return r; } +function testMask(mask: Mask, points: ArrayLike<number>) { + let r = 0; + for (let i = 0, _i = points.length; i < _i; i++) { + if (maskSearch(mask, points[i])) r += points[i]; + } + return r; +} + function run(f: () => number, n: number) { for (let i = 0; i < n; i++) f(); } (function () { - const size = 100000; + const size = 10000; const list = createData(size); const queryPoints = createData(size); let obj = prepareObj(list); let set = prepareSet(list); + let mask = prepareMask(list); console.log('list', testBinary(list, queryPoints)); console.log('obj', testObj(obj, queryPoints)); console.log('set', testSet(set, queryPoints)); + console.log('mask', testMask(mask, queryPoints)); + + console.log('----------------------') console.time('obj'); run(() => testObj(obj, queryPoints), 100); @@ -118,6 +151,12 @@ function run(f: () => number, n: number) { run(() => testBinary(list, queryPoints), 100); console.timeEnd('bin-search'); + console.time('mask-search'); + run(() => testMask(mask, queryPoints), 100); + console.timeEnd('mask-search'); + + console.log('----------------------') + console.time('prepare-obj'); run(() => prepareObj(list), 1); console.timeEnd('prepare-obj'); @@ -125,4 +164,8 @@ function run(f: () => number, n: number) { console.time('prepare-set'); run(() => prepareSet(list).size, 1); console.timeEnd('prepare-set'); + + console.time('prepare-mask'); + run(() => prepareMask(list).min, 1); + console.timeEnd('prepare-mask'); }()) diff --git a/src/perf-tests/sort.ts b/src/perf-tests/sort.ts index 16bae8b5b..8afc447fa 100644 --- a/src/perf-tests/sort.ts +++ b/src/perf-tests/sort.ts @@ -95,9 +95,9 @@ function heapSort(arr: number[]) { } function createTestData(n: number) { - const data = new Int32Array(n); //new Array(n); + const data = []; //new Int32Array(n); //new Array(n); for (let i = 0; i < n; i++) { - data[i] = (n * Math.random());// | 0; + data[i] = (n * Math.random()) | 0; } return data; @@ -142,18 +142,19 @@ function partition3(xs: number[], l: number, r: number) { } function partition3_1(xs: number[], l: number, r: number) { + 'use strict'; const v = medianPivot(xs, l, r); // console.log('P', v); // console.log('I', xs.slice(l, r + 1)); let equals = l, tail = r; - while (xs[tail] > v) --tail; + while (xs[tail] > v)--tail; for (let i = l; i <= tail; i++) { const t = xs[i]; if (t > v) { swap(xs, i, tail); tail--; - while (xs[tail] > v) --tail; + while (xs[tail] > v)--tail; i--; } else if (t === v) { swap(xs, i, equals); @@ -170,6 +171,8 @@ function partition3_1(xs: number[], l: number, r: number) { } function insertionSort(xs: number[], start: number, end: number) { + 'use strict'; + for (let i = start + 1; i <= end; i++) { const key = xs[i]; let j = i - 1; @@ -182,6 +185,8 @@ function insertionSort(xs: number[], start: number, end: number) { } function quickSort(xs: number[], low: number, high: number) { + 'use strict'; + while (low < high) { if (high - low < 16) { insertionSort(xs, low, high); @@ -211,6 +216,97 @@ function checkSorted(arr: ArrayLike<number>) { console.log('sorted'); } +function defaultCmp(a: number, b: number) { + if (a > b) return 1 + if (a < b) return -1 + return 0 +} + +function quicksortCmp(arr: number[], cmp: any, bb: number, ee: number) { + cmp = cmp || defaultCmp + var begin = bb || 0 + var end = (ee || arr.length) - 1 + + var stack = [] + var sp = -1 + var left = begin + var right = end + var tmp = 0.0 + //var tmp2 = 0.0 + + // function swap(a: number, b: number) { + // tmp2 = arr[a] + // arr[a] = arr[b] + // arr[b] = tmp2 + // } + + var i, j + + while (true) { + if (right - left <= 25) { + for (j = left + 1; j <= right; ++j) { + tmp = arr[j] + i = j - 1 + + while (i >= left && cmp(arr[i], tmp) > 0) { + arr[i + 1] = arr[i] + --i + } + + arr[i + 1] = tmp + } + + if (sp === -1) break + + right = stack[sp--] // ? + left = stack[sp--] + } else { + var median = (left + right) >> 1 + + i = left + 1 + j = right + + swap(arr, median, i) + + if (cmp(arr[left], arr[right]) > 0) { + swap(arr, left, right) + } + + if (cmp(arr[i], arr[right]) > 0) { + swap(arr, i, right) + } + + if (cmp(arr[left], arr[i]) > 0) { + swap(arr, left, i) + } + + tmp = arr[i] + + while (true) { + do i++; while (cmp(arr[i], tmp) < 0) + do j--; while (cmp(arr[j], tmp) > 0) + if (j < i) break + swap(arr, i, j) + } + + arr[left + 1] = arr[j] + arr[j] = tmp + + if (right - i + 1 >= j - left) { + stack[++sp] = i + stack[++sp] = right + right = j - 1 + } else { + stack[++sp] = left + stack[++sp] = j - 1 + left = i + } + } + } + + return arr +} + (function test() { // console.log(medianPivot([1, 2, 3], 0, 2)) // console.log(medianPivot([1, 3, 2], 0, 2)) @@ -219,7 +315,7 @@ function checkSorted(arr: ArrayLike<number>) { // console.log(medianPivot([2, 3, 1], 0, 2)) // console.log(medianPivot([3, 2, 1], 0, 2)) - const n = 10000; + const n = 1000; Array.prototype.sort.call(createTestData(n), (a: number, b: number) => a - b); mergeSort(createTestData(n)); @@ -231,6 +327,9 @@ function checkSorted(arr: ArrayLike<number>) { sd = createTestData(n); quickSort(sd as any, 0, sd.length - 1); + sd = createTestData(n); + quicksortCmp(sd as any, void 0, 0, sd.length - 1); + //console.log(sd); // sd = createTestData(n); @@ -268,7 +367,17 @@ function checkSorted(arr: ArrayLike<number>) { console.timeEnd('qs-sorted'); checkSorted(sd); - const reverseSorted = new Int32Array(n); + let reverseSorted = new Int32Array(n); + for (let i = 0; i < n; i++) { + reverseSorted[i] = sd[n - i - 1]; + } + + console.time('qs-reverse-sorted'); + quickSort(reverseSorted as any, 0, reverseSorted.length - 1); + console.timeEnd('qs-reverse-sorted'); + checkSorted(reverseSorted); + + reverseSorted = new Int32Array(n); for (let i = 0; i < n; i++) { reverseSorted[i] = sd[n - i - 1]; } @@ -278,10 +387,61 @@ function checkSorted(arr: ArrayLike<number>) { console.timeEnd('qs-reverse-sorted'); checkSorted(reverseSorted); + sd = createTestData(n); + checkSorted(sd); + console.time('qs'); + quickSort(sd as any, 0, sd.length - 1); + console.timeEnd('qs'); + checkSorted(sd); + console.log('swap count', swapCount); console.log('--------------'); + //console.log('quick', sd); + + sd = createTestData(n); + checkSorted(sd); + console.time('qs-a'); + quicksortCmp(sd as any, void 0, 0, sd.length - 1); + console.timeEnd('qs-a'); + checkSorted(sd); + + console.time('qs-a-sorted'); + quicksortCmp(sd as any, void 0, 0, sd.length - 1); + console.timeEnd('qs-a-sorted'); + checkSorted(sd); + + reverseSorted = new Int32Array(n); + for (let i = 0; i < n; i++) { + reverseSorted[i] = sd[n - i - 1]; + } + + console.time('qs-a-reverse-sorted'); + quicksortCmp(reverseSorted as any, void 0, 0, reverseSorted.length - 1); + console.timeEnd('qs-a-reverse-sorted'); + checkSorted(reverseSorted); + + reverseSorted = new Int32Array(n); + for (let i = 0; i < n; i++) { + reverseSorted[i] = sd[n - i - 1]; + } + + console.time('qs-a-reverse-sorted'); + quicksortCmp(reverseSorted as any, void 0, 0, reverseSorted.length - 1); + console.timeEnd('qs-a-reverse-sorted'); + checkSorted(reverseSorted); + + sd = createTestData(n); + checkSorted(sd); + console.time('qs-a'); + quicksortCmp(sd as any, void 0, 0, sd.length - 1); + console.timeEnd('qs-a'); + //console.log(sd); + checkSorted(sd); + + console.log('--------------'); + sd = createTestData(n); checkSorted(sd); console.time('native'); -- GitLab