data-structure-typed 1.41.3 → 1.41.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/README.md +561 -265
- package/benchmark/report.html +79 -0
- package/benchmark/report.json +343 -28
- package/dist/cjs/data-structures/binary-tree/binary-tree.js +11 -10
- package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/mjs/data-structures/binary-tree/binary-tree.js +11 -10
- package/dist/umd/data-structure-typed.min.js +1 -1
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +8 -4
- package/src/data-structures/binary-tree/binary-tree.ts +12 -9
- package/test/config.ts +1 -1
- package/test/performance/data-structures/binary-tree/avl-tree.test.ts +36 -0
- package/test/performance/data-structures/binary-tree/binary-tree.test.ts +45 -0
- package/test/performance/data-structures/binary-tree/bst.test.ts +36 -0
- package/test/performance/data-structures/graph/directed-graph.test.ts +49 -0
- package/test/performance/data-structures/heap/heap.test.ts +30 -0
- package/test/performance/data-structures/linked-list/doubly-linked-list.test.ts +40 -0
- package/test/performance/data-structures/linked-list/singly-linked-list.test.ts +34 -0
- package/test/performance/data-structures/priority-queue/max-priority-queue.test.ts +19 -0
- package/test/performance/data-structures/queue/deque.test.ts +8 -6
- package/test/performance/data-structures/queue/queue.test.ts +17 -12
- package/test/performance/data-structures/trie/trie.test.ts +22 -0
- package/test/performance/reportor.ts +183 -0
- package/test/performance/types/index.ts +1 -0
- package/test/performance/types/reportor.ts +3 -0
- package/test/types/utils/index.ts +1 -0
- package/test/types/utils/json2html.ts +1 -0
- package/test/unit/data-structures/binary-tree/rb-tree.test.ts +1 -1
- package/test/unit/data-structures/heap/heap.test.ts +5 -4
- package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +0 -23
- package/test/unit/data-structures/linked-list/linked-list.test.ts +3 -30
- package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +0 -21
- package/test/unit/data-structures/matrix/matrix2d.test.ts +1 -1
- package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +0 -32
- package/test/unit/data-structures/queue/queue.test.ts +3 -39
- package/test/utils/array.ts +5514 -0
- package/test/utils/big-o.ts +14 -8
- package/test/utils/console.ts +31 -0
- package/test/utils/index.ts +5 -0
- package/test/utils/is.ts +56 -0
- package/test/utils/json2html.ts +322 -0
- package/test/utils/number.ts +10 -0
- package/test/utils/string.ts +1 -0
- package/test/config.js +0 -4
- package/test/performance/index.ts +0 -47
- package/test/types/index.js +0 -29
- package/test/types/utils/big-o.js +0 -2
- package/test/types/utils/index.js +0 -29
- package/test/utils/big-o.js +0 -222
- package/test/utils/index.js +0 -30
- package/test/utils/number.js +0 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-structure-typed",
|
|
3
|
-
"version": "1.41.
|
|
3
|
+
"version": "1.41.5",
|
|
4
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.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/mjs/index.js",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"reformat": "npm run reformat:src && npm run reformat:test",
|
|
32
32
|
"update:subs": "npm i avl-tree-typed binary-tree-typed bst-typed heap-typed --save-dev",
|
|
33
33
|
"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",
|
|
34
|
-
"test": "jest",
|
|
34
|
+
"test": "jest --runInBand",
|
|
35
35
|
"test:integration": "npm run update:subs && jest --config jest.integration.config.js",
|
|
36
|
-
"benchmark": "ts-node test/performance/
|
|
36
|
+
"benchmark": "ts-node test/performance/reportor.ts",
|
|
37
37
|
"check:deps": "dependency-cruiser src",
|
|
38
38
|
"changelog": "auto-changelog",
|
|
39
39
|
"coverage:badge": "istanbul-badges-readme",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"copy:to-subs": "sh scripts/copy_to_all_subs.sh",
|
|
42
42
|
"publish:subs": "npm run copy:to-subs && sh scripts/publish_all_subs.sh",
|
|
43
43
|
"publish:docs": "sh scripts/publish_docs.sh",
|
|
44
|
-
"publish:all": "npm run ci && npm publish && npm run publish:docs && npm run publish:subs"
|
|
44
|
+
"publish:all": "npm run ci && npm run benchmark && npm publish && npm run publish:docs && npm run publish:subs"
|
|
45
45
|
},
|
|
46
46
|
"repository": {
|
|
47
47
|
"type": "git",
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"@types/benchmark": "^2.1.3",
|
|
61
61
|
"@types/jest": "^29.5.5",
|
|
62
62
|
"@types/node": "^20.8.2",
|
|
63
|
+
"@types/underscore": "^1.11.12",
|
|
63
64
|
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
|
64
65
|
"@typescript-eslint/parser": "^6.7.4",
|
|
65
66
|
"auto-changelog": "^2.4.0",
|
|
@@ -132,9 +133,12 @@
|
|
|
132
133
|
"UMD",
|
|
133
134
|
"esmodule",
|
|
134
135
|
"java.util",
|
|
136
|
+
"c++ stl",
|
|
135
137
|
"c++ std",
|
|
136
138
|
"Python collections",
|
|
137
139
|
"System.Collections.Generic",
|
|
140
|
+
"STL",
|
|
141
|
+
"stl",
|
|
138
142
|
"STD",
|
|
139
143
|
"std",
|
|
140
144
|
"util",
|
|
@@ -179,7 +179,10 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
179
179
|
while (queue.size > 0) {
|
|
180
180
|
const cur = queue.shift();
|
|
181
181
|
if (cur) {
|
|
182
|
-
if (newNode && cur.key === newNode.key)
|
|
182
|
+
if (newNode && cur.key === newNode.key) {
|
|
183
|
+
cur.value = newNode.value;
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
183
186
|
const inserted = this._addTo(newNode, cur);
|
|
184
187
|
if (inserted !== undefined) return inserted;
|
|
185
188
|
if (cur.left) queue.push(cur.left);
|
|
@@ -201,16 +204,16 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
201
204
|
return;
|
|
202
205
|
}
|
|
203
206
|
|
|
204
|
-
const key = typeof keyOrNode === 'number' ? keyOrNode : keyOrNode ? keyOrNode.key : undefined;
|
|
205
|
-
const existNode = key !== undefined ? this.getNode(key, (node: N) => node.key) : undefined;
|
|
207
|
+
// const key = typeof keyOrNode === 'number' ? keyOrNode : keyOrNode ? keyOrNode.key : undefined;
|
|
208
|
+
// const existNode = key !== undefined ? this.getNode(key, (node: N) => node.key) : undefined;
|
|
206
209
|
|
|
207
210
|
if (this.root) {
|
|
208
|
-
if (existNode) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
} else {
|
|
212
|
-
|
|
213
|
-
}
|
|
211
|
+
// if (existNode) {
|
|
212
|
+
// existNode.value = value;
|
|
213
|
+
// inserted = existNode;
|
|
214
|
+
// } else {
|
|
215
|
+
inserted = _bfs(this.root, needInsert);
|
|
216
|
+
// }
|
|
214
217
|
} else {
|
|
215
218
|
this._setRoot(needInsert);
|
|
216
219
|
if (needInsert !== null) {
|
package/test/config.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const isDebugTest =
|
|
1
|
+
export const isDebugTest = false;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {AVLTree} from '../../../../src';
|
|
2
|
+
import * as Benchmark from 'benchmark';
|
|
3
|
+
import {getRandomIntArray, magnitude} from '../../../utils';
|
|
4
|
+
|
|
5
|
+
const suite = new Benchmark.Suite();
|
|
6
|
+
const avl = new AVLTree<number>();
|
|
7
|
+
const {N_LOG_N} = magnitude;
|
|
8
|
+
const arr = getRandomIntArray(N_LOG_N, 0, N_LOG_N, true);
|
|
9
|
+
|
|
10
|
+
suite
|
|
11
|
+
.add(`${N_LOG_N} add randomly`, () => {
|
|
12
|
+
avl.clear();
|
|
13
|
+
for (let i = 0; i < arr.length; i++) {
|
|
14
|
+
avl.add(arr[i]);
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
.add(`${N_LOG_N} add & delete randomly`, () => {
|
|
18
|
+
avl.clear();
|
|
19
|
+
for (let i = 0; i < arr.length; i++) {
|
|
20
|
+
avl.add(arr[i]);
|
|
21
|
+
}
|
|
22
|
+
for (let i = 0; i < arr.length; i++) {
|
|
23
|
+
avl.delete(arr[i]);
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
.add(`${N_LOG_N} addMany`, () => {
|
|
27
|
+
avl.clear();
|
|
28
|
+
avl.addMany(arr);
|
|
29
|
+
})
|
|
30
|
+
.add(`${N_LOG_N} get`, () => {
|
|
31
|
+
for (let i = 0; i < arr.length; i++) {
|
|
32
|
+
avl.get(arr[i]);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export {suite};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {BinaryTree} from '../../../../src';
|
|
2
|
+
import * as Benchmark from 'benchmark';
|
|
3
|
+
import {getRandomIntArray, magnitude} from '../../../utils';
|
|
4
|
+
|
|
5
|
+
const suite = new Benchmark.Suite();
|
|
6
|
+
const biTree = new BinaryTree<number>();
|
|
7
|
+
const {N_LOG_N} = magnitude;
|
|
8
|
+
const arr = getRandomIntArray(N_LOG_N, 0, N_LOG_N, true);
|
|
9
|
+
|
|
10
|
+
suite
|
|
11
|
+
.add(`${N_LOG_N} add randomly`, () => {
|
|
12
|
+
biTree.clear();
|
|
13
|
+
for (let i = 0; i < arr.length; i++) {
|
|
14
|
+
biTree.add(arr[i]);
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
.add(`${N_LOG_N} add & delete randomly`, () => {
|
|
18
|
+
biTree.clear();
|
|
19
|
+
for (let i = 0; i < arr.length; i++) {
|
|
20
|
+
biTree.add(arr[i]);
|
|
21
|
+
}
|
|
22
|
+
for (let i = 0; i < arr.length; i++) {
|
|
23
|
+
biTree.delete(arr[i]);
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
.add(`${N_LOG_N} addMany`, () => {
|
|
27
|
+
biTree.clear();
|
|
28
|
+
biTree.addMany(arr);
|
|
29
|
+
})
|
|
30
|
+
.add(`${N_LOG_N} get`, () => {
|
|
31
|
+
for (let i = 0; i < arr.length; i++) {
|
|
32
|
+
biTree.get(arr[i]);
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
.add(`${N_LOG_N} dfs`, () => {
|
|
36
|
+
for (let i = 0; i < N_LOG_N; i++) biTree.dfs();
|
|
37
|
+
})
|
|
38
|
+
.add(`${N_LOG_N} bfs`, () => {
|
|
39
|
+
for (let i = 0; i < N_LOG_N; i++) biTree.bfs();
|
|
40
|
+
})
|
|
41
|
+
.add(`${N_LOG_N} morris`, () => {
|
|
42
|
+
for (let i = 0; i < N_LOG_N; i++) biTree.morris(n => n, 'pre');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export {suite};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {BST} from '../../../../src';
|
|
2
|
+
import * as Benchmark from 'benchmark';
|
|
3
|
+
import {getRandomIntArray, magnitude} from '../../../utils';
|
|
4
|
+
|
|
5
|
+
const suite = new Benchmark.Suite();
|
|
6
|
+
const bst = new BST<number>();
|
|
7
|
+
const {N_LOG_N} = magnitude;
|
|
8
|
+
const arr = getRandomIntArray(N_LOG_N, 0, N_LOG_N, true);
|
|
9
|
+
|
|
10
|
+
suite
|
|
11
|
+
.add(`${N_LOG_N} add randomly`, () => {
|
|
12
|
+
bst.clear();
|
|
13
|
+
for (let i = 0; i < arr.length; i++) {
|
|
14
|
+
bst.add(arr[i]);
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
.add(`${N_LOG_N} add & delete randomly`, () => {
|
|
18
|
+
bst.clear();
|
|
19
|
+
for (let i = 0; i < arr.length; i++) {
|
|
20
|
+
bst.add(arr[i]);
|
|
21
|
+
}
|
|
22
|
+
for (let i = 0; i < arr.length; i++) {
|
|
23
|
+
bst.delete(arr[i]);
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
.add(`${N_LOG_N} addMany`, () => {
|
|
27
|
+
bst.clear();
|
|
28
|
+
bst.addMany(arr);
|
|
29
|
+
})
|
|
30
|
+
.add(`${N_LOG_N} get`, () => {
|
|
31
|
+
for (let i = 0; i < arr.length; i++) {
|
|
32
|
+
bst.get(arr[i]);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export {suite};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {DirectedGraph} from '../../../../src';
|
|
2
|
+
import * as Benchmark from 'benchmark';
|
|
3
|
+
import {getRandomIndex, getRandomWords, magnitude} from '../../../utils';
|
|
4
|
+
|
|
5
|
+
const suite = new Benchmark.Suite();
|
|
6
|
+
const {THOUSAND} = magnitude;
|
|
7
|
+
const graph = new DirectedGraph<number, number>();
|
|
8
|
+
const vertexes = getRandomWords(THOUSAND);
|
|
9
|
+
|
|
10
|
+
suite
|
|
11
|
+
.add(`${THOUSAND} addVertex`, () => {
|
|
12
|
+
for (const v of vertexes) {
|
|
13
|
+
graph.addVertex(v);
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
.add(`${THOUSAND} addEdge`, () => {
|
|
17
|
+
for (let i = 0; i < THOUSAND; i++) {
|
|
18
|
+
const v1 = vertexes[getRandomIndex(vertexes)];
|
|
19
|
+
const v2 = vertexes[getRandomIndex(vertexes)];
|
|
20
|
+
graph.addEdge(v1, v2);
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
.add(`${THOUSAND} getVertex`, () => {
|
|
24
|
+
for (let i = 0; i < THOUSAND; i++) {
|
|
25
|
+
graph.getVertex(vertexes[getRandomIndex(vertexes)]);
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
.add(`${THOUSAND} getEdge`, () => {
|
|
29
|
+
for (let i = 0; i < THOUSAND; i++) {
|
|
30
|
+
graph.getEdge(vertexes[getRandomIndex(vertexes)], vertexes[getRandomIndex(vertexes)]);
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
.add(`tarjan`, () => {
|
|
34
|
+
// for (let i = 0; i < THOUSAND; i++) {
|
|
35
|
+
graph.tarjan(true);
|
|
36
|
+
// }
|
|
37
|
+
})
|
|
38
|
+
.add(`tarjan all`, () => {
|
|
39
|
+
// for (let i = 0; i < THOUSAND; i++) {
|
|
40
|
+
graph.tarjan(true, true, true, true);
|
|
41
|
+
// }
|
|
42
|
+
})
|
|
43
|
+
.add(`topologicalSort`, () => {
|
|
44
|
+
// for (let i = 0; i < THOUSAND; i++) {
|
|
45
|
+
graph.topologicalSort('key');
|
|
46
|
+
// }
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export {suite};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {FibonacciHeap, Heap} from '../../../../src';
|
|
2
|
+
import * as Benchmark from 'benchmark';
|
|
3
|
+
import {magnitude} from '../../../utils';
|
|
4
|
+
|
|
5
|
+
const suite = new Benchmark.Suite();
|
|
6
|
+
const {N_LOG_N} = magnitude;
|
|
7
|
+
|
|
8
|
+
suite
|
|
9
|
+
.add(`${N_LOG_N} add & pop`, () => {
|
|
10
|
+
const heap = new Heap<number>({comparator: (a, b) => b - a});
|
|
11
|
+
|
|
12
|
+
for (let i = 0; i < N_LOG_N; i++) {
|
|
13
|
+
heap.add(i);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < N_LOG_N; i++) {
|
|
17
|
+
heap.pop();
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
.add(`${N_LOG_N} fib add & pop`, () => {
|
|
21
|
+
const fbHeap = new FibonacciHeap<number>();
|
|
22
|
+
for (let i = 1; i <= N_LOG_N; i++) {
|
|
23
|
+
fbHeap.push(i);
|
|
24
|
+
}
|
|
25
|
+
for (let i = 1; i <= N_LOG_N; i++) {
|
|
26
|
+
fbHeap.pop();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export {suite};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {DoublyLinkedList, DoublyLinkedListNode} from '../../../../src';
|
|
2
|
+
import * as Benchmark from 'benchmark';
|
|
3
|
+
import {magnitude} from '../../../utils';
|
|
4
|
+
|
|
5
|
+
const suite = new Benchmark.Suite();
|
|
6
|
+
const {LINEAR, N_LOG_N} = magnitude;
|
|
7
|
+
|
|
8
|
+
suite
|
|
9
|
+
.add(`${LINEAR} unshift`, () => {
|
|
10
|
+
const list = new DoublyLinkedList<number>();
|
|
11
|
+
|
|
12
|
+
for (let i = 0; i < LINEAR; i++) {
|
|
13
|
+
list.unshift(i);
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
.add(`${LINEAR} unshift & shift`, () => {
|
|
17
|
+
const list = new DoublyLinkedList<number>();
|
|
18
|
+
|
|
19
|
+
for (let i = 0; i < LINEAR; i++) {
|
|
20
|
+
list.unshift(i);
|
|
21
|
+
}
|
|
22
|
+
for (let i = 0; i < LINEAR; i++) {
|
|
23
|
+
list.shift();
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
.add(`${N_LOG_N} insertBefore`, () => {
|
|
27
|
+
const doublyList = new DoublyLinkedList<number>();
|
|
28
|
+
let midNode: DoublyLinkedListNode | null = null;
|
|
29
|
+
const midIndex = Math.floor(N_LOG_N / 2);
|
|
30
|
+
for (let i = 0; i < N_LOG_N; i++) {
|
|
31
|
+
doublyList.push(i);
|
|
32
|
+
if (i === midIndex) {
|
|
33
|
+
midNode = doublyList.getNode(i);
|
|
34
|
+
} else if (i > midIndex && midNode) {
|
|
35
|
+
doublyList.insertBefore(midNode, i);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export {suite};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {SinglyLinkedList, SinglyLinkedListNode} from '../../../../src';
|
|
2
|
+
import * as Benchmark from 'benchmark';
|
|
3
|
+
import {magnitude} from '../../../utils';
|
|
4
|
+
|
|
5
|
+
const suite = new Benchmark.Suite();
|
|
6
|
+
const {N_LOG_N} = magnitude;
|
|
7
|
+
|
|
8
|
+
suite
|
|
9
|
+
.add(`${N_LOG_N} push & pop`, () => {
|
|
10
|
+
const list = new SinglyLinkedList<number>();
|
|
11
|
+
|
|
12
|
+
for (let i = 0; i < N_LOG_N; i++) {
|
|
13
|
+
list.push(i);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < N_LOG_N; i++) {
|
|
17
|
+
list.pop();
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
.add(`${N_LOG_N} insertBefore`, () => {
|
|
21
|
+
const singlyList = new SinglyLinkedList<number>();
|
|
22
|
+
let midSinglyNode: SinglyLinkedListNode | null = null;
|
|
23
|
+
const midIndex = Math.floor(N_LOG_N / 2);
|
|
24
|
+
for (let i = 0; i < N_LOG_N; i++) {
|
|
25
|
+
singlyList.push(i);
|
|
26
|
+
if (i === midIndex) {
|
|
27
|
+
midSinglyNode = singlyList.getNode(i);
|
|
28
|
+
} else if (i > midIndex && midSinglyNode) {
|
|
29
|
+
singlyList.insertBefore(midSinglyNode.value, i);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export {suite};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {MaxPriorityQueue} from '../../../../src';
|
|
2
|
+
import * as Benchmark from 'benchmark';
|
|
3
|
+
import {magnitude} from '../../../utils';
|
|
4
|
+
|
|
5
|
+
const suite = new Benchmark.Suite();
|
|
6
|
+
const {TEN_THOUSAND} = magnitude;
|
|
7
|
+
|
|
8
|
+
suite.add(`${TEN_THOUSAND} refill & poll`, () => {
|
|
9
|
+
const nodes = Array.from(
|
|
10
|
+
new Set<number>(Array.from(new Array(TEN_THOUSAND), () => Math.floor(Math.random() * TEN_THOUSAND * 100)))
|
|
11
|
+
);
|
|
12
|
+
const maxPQ = new MaxPriorityQueue<number>();
|
|
13
|
+
maxPQ.refill(nodes);
|
|
14
|
+
while (maxPQ.size > 0) {
|
|
15
|
+
maxPQ.poll();
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export {suite};
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
import {Deque} from
|
|
1
|
+
import {Deque} from '../../../../src';
|
|
2
2
|
import * as Benchmark from 'benchmark';
|
|
3
|
+
import {magnitude} from '../../../utils';
|
|
3
4
|
|
|
4
5
|
export const suite = new Benchmark.Suite();
|
|
6
|
+
const {LINEAR} = magnitude;
|
|
5
7
|
|
|
6
8
|
suite
|
|
7
|
-
.add(
|
|
9
|
+
.add(`${LINEAR} push`, () => {
|
|
8
10
|
const deque = new Deque<number>();
|
|
9
|
-
for (let i = 0; i <
|
|
11
|
+
for (let i = 0; i < LINEAR; i++) {
|
|
10
12
|
deque.push(i);
|
|
11
13
|
}
|
|
12
14
|
})
|
|
13
|
-
.add(
|
|
15
|
+
.add(`${LINEAR} shift`, () => {
|
|
14
16
|
const deque = new Deque<number>();
|
|
15
|
-
for (let i = 0; i <
|
|
17
|
+
for (let i = 0; i < LINEAR; i++) {
|
|
16
18
|
deque.push(i);
|
|
17
19
|
deque.shift();
|
|
18
20
|
}
|
|
19
|
-
})
|
|
21
|
+
});
|
|
@@ -1,20 +1,25 @@
|
|
|
1
|
-
import {Queue} from
|
|
2
|
-
|
|
1
|
+
import {Queue} from '../../../../src';
|
|
3
2
|
import * as Benchmark from 'benchmark';
|
|
3
|
+
import {magnitude} from '../../../utils';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const suite = new Benchmark.Suite();
|
|
6
|
+
const {LINEAR} = magnitude;
|
|
6
7
|
|
|
7
8
|
suite
|
|
8
|
-
.add(
|
|
9
|
+
.add(`${LINEAR} push`, () => {
|
|
9
10
|
const queue = new Queue<number>();
|
|
10
|
-
|
|
11
|
+
|
|
12
|
+
for (let i = 0; i < LINEAR; i++) {
|
|
11
13
|
queue.push(i);
|
|
12
14
|
}
|
|
13
15
|
})
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
.add(`${LINEAR} push & shift`, () => {
|
|
17
|
+
const queue = new Queue<number>();
|
|
18
|
+
|
|
19
|
+
for (let i = 0; i < LINEAR; i++) {
|
|
20
|
+
queue.push(i);
|
|
21
|
+
queue.shift();
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export {suite};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {Trie} from '../../../../src';
|
|
2
|
+
import * as Benchmark from 'benchmark';
|
|
3
|
+
import {getRandomWords, magnitude} from '../../../utils';
|
|
4
|
+
|
|
5
|
+
const suite = new Benchmark.Suite();
|
|
6
|
+
const {HUNDRED_THOUSAND} = magnitude;
|
|
7
|
+
const trie = new Trie();
|
|
8
|
+
const randomWords = getRandomWords(HUNDRED_THOUSAND, false);
|
|
9
|
+
|
|
10
|
+
suite
|
|
11
|
+
.add(`${HUNDRED_THOUSAND} push`, () => {
|
|
12
|
+
for (let i = 0; i < randomWords.length; i++) {
|
|
13
|
+
trie.add(randomWords[i]);
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
.add(`${HUNDRED_THOUSAND} getWords`, () => {
|
|
17
|
+
for (let i = 0; i < randomWords.length; i++) {
|
|
18
|
+
trie.getWords(randomWords[i]);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export {suite};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import * as Benchmark from 'benchmark';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as fastGlob from 'fast-glob';
|
|
5
|
+
import {Color, numberFix, render} from '../utils';
|
|
6
|
+
import {PerformanceTest} from './types';
|
|
7
|
+
|
|
8
|
+
const reportDistPath = 'benchmark';
|
|
9
|
+
const testDir = path.join(__dirname, 'data-structures');
|
|
10
|
+
const testFiles = fastGlob.sync(path.join(testDir, '**', '*.test.ts'));
|
|
11
|
+
|
|
12
|
+
const report: {[key: string]: any} = {};
|
|
13
|
+
|
|
14
|
+
let completedCount = 0;
|
|
15
|
+
|
|
16
|
+
const performanceTests: PerformanceTest[] = [];
|
|
17
|
+
const {GREEN, BOLD, END, YELLOW, GRAY, CYAN, BG_YELLOW} = Color;
|
|
18
|
+
|
|
19
|
+
testFiles.forEach((file: string) => {
|
|
20
|
+
const testName = path.basename(file, '.test.ts');
|
|
21
|
+
const testFunction = require(file);
|
|
22
|
+
const {suite} = testFunction;
|
|
23
|
+
if (suite) performanceTests.push({testName, suite, file});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const composeReport = () => {
|
|
27
|
+
if (!fs.existsSync(reportDistPath)) fs.mkdirSync(reportDistPath, {recursive: true});
|
|
28
|
+
|
|
29
|
+
const filePath = path.join(reportDistPath, 'report.json');
|
|
30
|
+
const htmlFilePath = path.join(reportDistPath, 'report.html');
|
|
31
|
+
fs.writeFileSync(filePath, JSON.stringify(report, null, 2));
|
|
32
|
+
let html = `<!DOCTYPE html>
|
|
33
|
+
<html lang="en">
|
|
34
|
+
<head>
|
|
35
|
+
<meta charset="UTF-8">
|
|
36
|
+
<title>performance of data-structure-typed</title>
|
|
37
|
+
<style>
|
|
38
|
+
*{
|
|
39
|
+
box-sizing: border-box;
|
|
40
|
+
}
|
|
41
|
+
#json-to-html {
|
|
42
|
+
padding: 0 10px 20px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.json-to-html-label {
|
|
46
|
+
font-size: 2rem;
|
|
47
|
+
margin: 2rem 0 0 3px;
|
|
48
|
+
}
|
|
49
|
+
.content table {
|
|
50
|
+
width: 100%;
|
|
51
|
+
table-layout: fixed;
|
|
52
|
+
border-collapse: collapse;
|
|
53
|
+
margin-top: 10px;
|
|
54
|
+
font-size: 16px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.content table th,
|
|
58
|
+
.content table td {
|
|
59
|
+
padding: 8px 12px;
|
|
60
|
+
text-align: left;
|
|
61
|
+
border: 1px solid #ddd;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.content table th {
|
|
65
|
+
background-color: #f2f2f2;
|
|
66
|
+
font-weight: bold;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.content table tr:nth-child(odd) {
|
|
70
|
+
background-color: #ffffff;
|
|
71
|
+
}
|
|
72
|
+
</style>
|
|
73
|
+
</head>
|
|
74
|
+
<body>
|
|
75
|
+
<div id="json-to-html">`;
|
|
76
|
+
let htmlTables = '';
|
|
77
|
+
for (const r in report) {
|
|
78
|
+
if (report.hasOwnProperty(r)) {
|
|
79
|
+
htmlTables += render(report[r].testName, report[r].benchmarks, {
|
|
80
|
+
plainHtml: true,
|
|
81
|
+
'<>': 'table',
|
|
82
|
+
html: [
|
|
83
|
+
{
|
|
84
|
+
'<>': 'tr',
|
|
85
|
+
html: [
|
|
86
|
+
{'<>': 'td', html: '${name}'},
|
|
87
|
+
{'<>': 'td', html: '${periodMS}'},
|
|
88
|
+
{'<>': 'td', html: '${mean}'}
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
html += htmlTables;
|
|
96
|
+
html += `</div>
|
|
97
|
+
</body>
|
|
98
|
+
</html>`;
|
|
99
|
+
writeIntoMarkdown(htmlTables);
|
|
100
|
+
fs.writeFileSync(htmlFilePath, html);
|
|
101
|
+
console.log(`Performance ${BOLD}${GREEN}report${END} file generated`);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
function writeIntoMarkdown(html: string) {
|
|
105
|
+
const parentDirectory = path.resolve(__dirname, '../..'); // The path to the parent directory
|
|
106
|
+
const markdownFilePath = path.join(parentDirectory, 'README.md'); // Path to README.md file
|
|
107
|
+
const textToInsert = html;
|
|
108
|
+
|
|
109
|
+
// Read the original README.md file
|
|
110
|
+
fs.readFile(markdownFilePath, 'utf8', (err, data) => {
|
|
111
|
+
if (err) {
|
|
112
|
+
console.error('Unable to read README.md file:', err);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Find the location in the README.md file where you want to insert the text, for example under a specific tag
|
|
117
|
+
const insertMarker = '## Benchmark';
|
|
118
|
+
|
|
119
|
+
const index = data.indexOf(insertMarker);
|
|
120
|
+
if (index === -1) {
|
|
121
|
+
console.error('Unable to find insertion point');
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// insert text
|
|
126
|
+
const updatedMarkdown =
|
|
127
|
+
data.slice(0, index + insertMarker.length) + '\n' + textToInsert + data.slice(index + insertMarker.length);
|
|
128
|
+
|
|
129
|
+
// Try writing the modified content back to the README.md file
|
|
130
|
+
fs.writeFile(markdownFilePath, updatedMarkdown, 'utf8', err => {
|
|
131
|
+
if (err) {
|
|
132
|
+
console.error('Unable to write to README.md file:', err);
|
|
133
|
+
} else {
|
|
134
|
+
console.log('The tables have been successfully inserted into the README.md file!');
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
performanceTests.forEach(item => {
|
|
141
|
+
const {suite, testName, file} = item;
|
|
142
|
+
const relativeFilePath = path.relative(__dirname, file);
|
|
143
|
+
const directory = path.dirname(relativeFilePath);
|
|
144
|
+
const fileName = path.basename(relativeFilePath);
|
|
145
|
+
console.log(`${BG_YELLOW}Running in${END}: ${GRAY}${directory}/${END}${CYAN}${fileName}${END}`);
|
|
146
|
+
|
|
147
|
+
if (suite) {
|
|
148
|
+
let runTime = 0;
|
|
149
|
+
suite
|
|
150
|
+
.on('complete', function (this: Benchmark.Suite) {
|
|
151
|
+
completedCount++;
|
|
152
|
+
report[testName] = {};
|
|
153
|
+
report[testName].benchmarks = this.map((benchmark: Benchmark) => {
|
|
154
|
+
runTime += benchmark.times.elapsed;
|
|
155
|
+
return {
|
|
156
|
+
'test name': benchmark.name,
|
|
157
|
+
'time taken (ms)': numberFix(benchmark.times.period * 1000, 2),
|
|
158
|
+
'executions per sec': numberFix(benchmark.hz, 2),
|
|
159
|
+
'executed times': numberFix(benchmark.count, 0),
|
|
160
|
+
'sample mean (secs)': numberFix(benchmark.stats.mean, 2),
|
|
161
|
+
'sample deviation': numberFix(benchmark.stats.deviation, 2)
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
report[testName].testName = testName;
|
|
166
|
+
const isDone = completedCount === performanceTests.length;
|
|
167
|
+
runTime = Number(runTime.toFixed(2));
|
|
168
|
+
const isTimeWarn = runTime > 120;
|
|
169
|
+
console.log(
|
|
170
|
+
// `Files: ${GREEN}${testFileCount}${END} `,
|
|
171
|
+
// `Suites: ${GREEN}${performanceTests.length}${END} `,
|
|
172
|
+
`Suites Progress: ${isDone ? GREEN : YELLOW}${completedCount}${END}/${isDone ? GREEN : YELLOW}${
|
|
173
|
+
performanceTests.length
|
|
174
|
+
}${END}`,
|
|
175
|
+
`Time: ${isTimeWarn ? YELLOW : GREEN}${runTime}s${END}`
|
|
176
|
+
);
|
|
177
|
+
if (isDone) {
|
|
178
|
+
composeReport();
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
.run({async: false});
|
|
182
|
+
}
|
|
183
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './reportor';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type Json2htmlOptions = {plainHtml?: boolean} & Partial<{[key: string]: any}>;
|