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