Skip to content

Commit

Permalink
[binary-tree] Merge the operation of modifying the value into the ins…
Browse files Browse the repository at this point in the history
…ert query process to improve performance. [benchmark] Enhance performance test cases and move existing performance tests from unit tests to the 'performance' section. Improve the benchmark test report. Refine the logic of the report generator.
  • Loading branch information
zrwusa committed Nov 2, 2023
1 parent 9a87fe1 commit 4614773
Show file tree
Hide file tree
Showing 41 changed files with 346 additions and 557 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -916,3 +916,32 @@ optimal approach to data structure design.
</tbody>
</table>
## Benchmark
<div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>avl-tree</span></div>
<div class="content"><table><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>executed times</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>add 1000 randomly</td><td>2.39</td><td>418.91</td><td>22</td><td>0.00</td><td>6.47e-5</td></tr><tr><td>delete 1000 randomly</td><td>0.06</td><td>1.77e+4</td><td>917</td><td>5.66e-5</td><td>1.90e-6</td></tr><tr><td>addMany 1000</td><td>3.32</td><td>301.33</td><td>17</td><td>0.00</td><td>5.90e-4</td></tr><tr><td>get 1000</td><td>55.03</td><td>18.17</td><td>1</td><td>0.06</td><td>0.00</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>binary-tree</span></div>
<div class="content"><table><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>executed times</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>add 1000</td><td>66.49</td><td>15.04</td><td>3</td><td>0.07</td><td>0.00</td></tr><tr><td>delete 1000</td><td>24.04</td><td>41.60</td><td>1106</td><td>0.02</td><td>0.04</td></tr><tr><td>addMany 1000</td><td>9.05</td><td>110.44</td><td>6</td><td>0.01</td><td>2.88e-4</td></tr><tr><td>get 1000</td><td>32.12</td><td>31.13</td><td>2</td><td>0.03</td><td>6.75e-4</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>bst</span></div>
<div class="content"><table><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>executed times</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>add 1000 randomly</td><td>2.27</td><td>440.62</td><td>23</td><td>0.00</td><td>1.42e-4</td></tr><tr><td>delete 1000 randomly</td><td>0.05</td><td>2.19e+4</td><td>1174</td><td>4.57e-5</td><td>1.97e-6</td></tr><tr><td>addMany 1000 balanced</td><td>2.93</td><td>341.38</td><td>19</td><td>0.00</td><td>1.13e-4</td></tr><tr><td>get 1000</td><td>62.85</td><td>15.91</td><td>1</td><td>0.06</td><td>0.01</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>heap</span></div>
<div class="content"><table><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>executed times</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>add & 1000</td><td>0.35</td><td>2878.39</td><td>149</td><td>3.47e-4</td><td>1.93e-5</td></tr><tr><td>fib add & pop 1000</td><td>3.98</td><td>251.35</td><td>14</td><td>0.00</td><td>1.32e-4</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>doubly-linked-list</span></div>
<div class="content"><table><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>executed times</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>unshift 1000000</td><td>193.19</td><td>5.18</td><td>1</td><td>0.19</td><td>0.04</td></tr><tr><td>unshift & shift 1000000</td><td>170.35</td><td>5.87</td><td>1</td><td>0.17</td><td>0.03</td></tr><tr><td>insertBefore 1000</td><td>0.03</td><td>3.43e+4</td><td>1888</td><td>2.91e-5</td><td>6.03e-6</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>singly-linked-list</span></div>
<div class="content"><table><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>executed times</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>push & pop 1000</td><td>1.79</td><td>560.08</td><td>29</td><td>0.00</td><td>7.70e-5</td></tr><tr><td>insertBefore 1000</td><td>2.31</td><td>433.45</td><td>22</td><td>0.00</td><td>5.52e-5</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>max-priority-queue</span></div>
<div class="content"><table><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>executed times</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>refill & poll 1000000</td><td>1859.40</td><td>0.54</td><td>1</td><td>1.86</td><td>0.03</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>deque</span></div>
<div class="content"><table><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>executed times</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>push 1000000</td><td>215.00</td><td>4.65</td><td>1</td><td>0.22</td><td>0.01</td></tr><tr><td>shift 1000000</td><td>25.04</td><td>39.94</td><td>3</td><td>0.03</td><td>0.00</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>queue</span></div>
<div class="content"><table><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>executed times</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>push 1000000</td><td>41.81</td><td>23.92</td><td>2</td><td>0.04</td><td>0.00</td></tr><tr><td>push & shift 1000000</td><td>79.17</td><td>12.63</td><td>1</td><td>0.08</td><td>8.70e-4</td></tr></table></div>
</div>
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-structure-typed",
"version": "1.41.3",
"version": "1.41.4",
"description": "Data Structures of Javascript & TypeScript. Binary Tree, BST, Graph, Heap, Priority Queue, Linked List, Queue, Deque, Stack, AVL Tree, Tree Multiset, Trie, Directed Graph, Undirected Graph, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue.",
"main": "dist/cjs/index.js",
"module": "dist/mjs/index.js",
Expand Down Expand Up @@ -31,7 +31,7 @@
"reformat": "npm run reformat:src && npm run reformat:test",
"update:subs": "npm i avl-tree-typed binary-tree-typed bst-typed heap-typed --save-dev",
"install:all-subs": "npm i avl-tree-typed binary-tree-typed bst-typed deque-typed directed-graph-typed doubly-linked-list-typed graph-typed heap-typed linked-list-typed max-heap-typed max-priority-queue-typed min-heap-typed min-priority-queue-typed priority-queue-typed singly-linked-list-typed stack-typed tree-multiset-typed trie-typed undirected-graph-typed queue-typed --save-dev",
"test": "jest",
"test": "jest --runInBand",
"test:integration": "npm run update:subs && jest --config jest.integration.config.js",
"benchmark": "ts-node test/performance/reportor.ts",
"check:deps": "dependency-cruiser src",
Expand Down
21 changes: 12 additions & 9 deletions src/data-structures/binary-tree/binary-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,10 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
while (queue.size > 0) {
const cur = queue.shift();
if (cur) {
if (newNode && cur.key === newNode.key) return;
if (newNode && cur.key === newNode.key) {
cur.value = newNode.value;
return;
}
const inserted = this._addTo(newNode, cur);
if (inserted !== undefined) return inserted;
if (cur.left) queue.push(cur.left);
Expand All @@ -201,16 +204,16 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
return;
}

const key = typeof keyOrNode === 'number' ? keyOrNode : keyOrNode ? keyOrNode.key : undefined;
const existNode = key !== undefined ? this.getNode(key, (node: N) => node.key) : undefined;
// const key = typeof keyOrNode === 'number' ? keyOrNode : keyOrNode ? keyOrNode.key : undefined;
// const existNode = key !== undefined ? this.getNode(key, (node: N) => node.key) : undefined;

if (this.root) {
if (existNode) {
existNode.value = value;
inserted = existNode;
} else {
inserted = _bfs(this.root, needInsert);
}
// if (existNode) {
// existNode.value = value;
// inserted = existNode;
// } else {
inserted = _bfs(this.root, needInsert);
// }
} else {
this._setRoot(needInsert);
if (needInsert !== null) {
Expand Down
4 changes: 0 additions & 4 deletions test/config.js

This file was deleted.

24 changes: 24 additions & 0 deletions test/performance/data-structures/binary-tree/avl-tree.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {AVLTree} from '../../../../src';
import * as Benchmark from 'benchmark';
import {magnitude, randomInt, randomIntArray} from '../../../utils';

const suite = new Benchmark.Suite();
const avl = new AVLTree<number>();
const {N_LOG_N} = magnitude;

suite
.add(`add ${N_LOG_N} randomly`, () => {
for (let i = 0; i < N_LOG_N; i++) avl.add(randomInt(0, N_LOG_N));
})
.add(`delete ${N_LOG_N} randomly`, () => {
for (let i = 0; i < N_LOG_N; i++) avl.delete(randomInt(0, N_LOG_N));
})
.add(`addMany ${N_LOG_N}`, () => {
const arr = randomIntArray(N_LOG_N);
avl.addMany(arr);
})
.add(`get ${N_LOG_N}`, () => {
for (let i = 0; i < N_LOG_N; i++) avl.get(randomInt(-N_LOG_N, N_LOG_N));
});

export {suite};
29 changes: 18 additions & 11 deletions test/performance/data-structures/binary-tree/binary-tree.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import {BinaryTree} from '../../../../src';

import * as Benchmark from 'benchmark';
import {magnitude, randomInt, randomIntArray} from '../../../utils';

export const suite = new Benchmark.Suite();
const bt = new BinaryTree<number>();
const suite = new Benchmark.Suite();
const biTree = new BinaryTree<number>();
const {N_LOG_N} = magnitude;

suite
.add('add 1000', () => {
for (let i = 0; i < 1000; i++) {
bt.add(i);
}
.add(`add ${N_LOG_N}`, () => {
for (let i = 0; i < N_LOG_N; i++) biTree.add(randomInt(-N_LOG_N, N_LOG_N));
})
.add(`delete ${N_LOG_N}`, () => {
for (let i = 0; i < N_LOG_N; i++) biTree.delete(randomInt(-N_LOG_N, N_LOG_N));
})
.add('add & delete 1000', () => {
for (let i = 0; i < 1000; i++) {
bt.delete(i);
}
.add(`addMany ${N_LOG_N}`, () => {
biTree.clear();
const arr = randomIntArray(N_LOG_N);
biTree.addMany(arr);
})
.add(`get ${N_LOG_N}`, () => {
for (let i = 0; i < N_LOG_N; i++) biTree.get(randomInt(-N_LOG_N, N_LOG_N));
});

export {suite};
28 changes: 17 additions & 11 deletions test/performance/data-structures/binary-tree/bst.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import {BST} from '../../../../src';

import * as Benchmark from 'benchmark';
import {magnitude, randomInt, randomIntArray} from '../../../utils';

export const suite = new Benchmark.Suite();
const bt = new BST<number>();
const suite = new Benchmark.Suite();
const bst = new BST<number>();
const {N_LOG_N} = magnitude;

suite
.add('add 1000', () => {
for (let i = 0; i < 1000; i++) {
bt.add(i);
}
.add(`add ${N_LOG_N} randomly`, () => {
for (let i = 0; i < N_LOG_N; i++) bst.add(randomInt(0, N_LOG_N));
})
.add(`delete ${N_LOG_N} randomly`, () => {
for (let i = 0; i < N_LOG_N; i++) bst.delete(randomInt(0, N_LOG_N));
})
.add('add & delete 1000', () => {
for (let i = 0; i < 1000; i++) {
bt.delete(i);
}
.add(`addMany ${N_LOG_N} balanced`, () => {
const arr = randomIntArray(N_LOG_N);
bst.addMany(arr);
})
.add(`get ${N_LOG_N}`, () => {
for (let i = 0; i < N_LOG_N; i++) bst.get(randomInt(-N_LOG_N, N_LOG_N));
});

export {suite};
30 changes: 30 additions & 0 deletions test/performance/data-structures/heap/heap.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {FibonacciHeap, Heap} from '../../../../src';
import * as Benchmark from 'benchmark';
import {magnitude} from '../../../utils';

const suite = new Benchmark.Suite();
const {N_LOG_N} = magnitude;

suite
.add(`add & ${N_LOG_N}`, () => {
const heap = new Heap<number>({comparator: (a, b) => b - a});

for (let i = 0; i < N_LOG_N; i++) {
heap.add(i);
}

for (let i = 0; i < N_LOG_N; i++) {
heap.pop();
}
})
.add(`fib add & pop ${N_LOG_N}`, () => {
const fbHeap = new FibonacciHeap<number>();
for (let i = 1; i <= N_LOG_N; i++) {
fbHeap.push(i);
}
for (let i = 1; i <= N_LOG_N; i++) {
fbHeap.pop();
}
});

export {suite};
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {DoublyLinkedList, DoublyLinkedListNode} from '../../../../src';
import * as Benchmark from 'benchmark';
import {magnitude} from '../../../utils';

const suite = new Benchmark.Suite();
const {LINEAR, N_LOG_N} = magnitude;

suite
.add(`unshift ${LINEAR}`, () => {
const list = new DoublyLinkedList<number>();

for (let i = 0; i < LINEAR; i++) {
list.unshift(i);
}
})
.add(`unshift & shift ${LINEAR}`, () => {
const list = new DoublyLinkedList<number>();

for (let i = 0; i < LINEAR; i++) {
list.unshift(i);
}
for (let i = 0; i < LINEAR; i++) {
list.shift();
}
})
.add(`insertBefore ${N_LOG_N}`, () => {
const doublyList = new DoublyLinkedList<number>();
let midNode: DoublyLinkedListNode | null = null;
const midIndex = Math.floor(N_LOG_N / 2);
for (let i = 0; i < N_LOG_N; i++) {
doublyList.push(i);
if (i === midIndex) {
midNode = doublyList.getNode(i);
} else if (i > midIndex && midNode) {
doublyList.insertBefore(midNode, i);
}
}
});

export {suite};
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {SinglyLinkedList, SinglyLinkedListNode} from '../../../../src';
import * as Benchmark from 'benchmark';
import {magnitude} from '../../../utils';

const suite = new Benchmark.Suite();
const {N_LOG_N} = magnitude;

suite
.add(`push & pop ${N_LOG_N}`, () => {
const list = new SinglyLinkedList<number>();

for (let i = 0; i < N_LOG_N; i++) {
list.push(i);
}

for (let i = 0; i < N_LOG_N; i++) {
list.pop();
}
})
.add(`insertBefore ${N_LOG_N}`, () => {
const singlyList = new SinglyLinkedList<number>();
let midSinglyNode: SinglyLinkedListNode | null = null;
const midIndex = Math.floor(N_LOG_N / 2);
for (let i = 0; i < N_LOG_N; i++) {
singlyList.push(i);
if (i === midIndex) {
midSinglyNode = singlyList.getNode(i);
} else if (i > midIndex && midSinglyNode) {
singlyList.insertBefore(midSinglyNode.value, i);
}
}
});

export {suite};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {MaxPriorityQueue} from '../../../../src';
import * as Benchmark from 'benchmark';
import {magnitude} from '../../../utils';

const suite = new Benchmark.Suite();
const {LINEAR} = magnitude;

suite.add(`refill & poll ${LINEAR}`, () => {
const nodes = Array.from(
new Set<number>(Array.from(new Array(LINEAR), () => Math.floor(Math.random() * LINEAR * 100)))
);
const maxPQ = new MaxPriorityQueue<number>();
maxPQ.refill(nodes);
while (maxPQ.size > 0) {
maxPQ.poll();
}
});

export {suite};
10 changes: 6 additions & 4 deletions test/performance/data-structures/queue/deque.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import {Deque} from '../../../../src';
import * as Benchmark from 'benchmark';
import {magnitude} from '../../../utils';

export const suite = new Benchmark.Suite();
const {LINEAR} = magnitude;

suite
.add('push', () => {
.add(`push ${LINEAR}`, () => {
const deque = new Deque<number>();
for (let i = 0; i < 10; i++) {
for (let i = 0; i < LINEAR; i++) {
deque.push(i);
}
})
.add('shift', () => {
.add(`shift ${LINEAR}`, () => {
const deque = new Deque<number>();
for (let i = 0; i < 10; i++) {
for (let i = 0; i < LINEAR; i++) {
deque.push(i);
deque.shift();
}
Expand Down
17 changes: 11 additions & 6 deletions test/performance/data-structures/queue/queue.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
import {Queue} from '../../../../src';

import * as Benchmark from 'benchmark';
import {magnitude} from '../../../utils';

export const suite = new Benchmark.Suite();
const suite = new Benchmark.Suite();
const {LINEAR} = magnitude;

suite
.add('push 1000000', () => {
.add(`push ${LINEAR}`, () => {
const queue = new Queue<number>();
for (let i = 0; i < 1000000; i++) {

for (let i = 0; i < LINEAR; i++) {
queue.push(i);
}
})
.add('push & shift 1000000', () => {
.add(`push & shift ${LINEAR}`, () => {
const queue = new Queue<number>();
for (let i = 0; i < 1000000; i++) {

for (let i = 0; i < LINEAR; i++) {
queue.push(i);
queue.shift();
}
});

export {suite};
Loading

0 comments on commit 4614773

Please sign in to comment.