mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
feat: The performance report generator supports parameter filtering commands, which can be used to run specific tests individually. It generates individual performance comparison reports. Enrich the COMMANDS.md document.
This commit is contained in:
parent
be6ad5473b
commit
f9b6f313c6
|
@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file.
|
|||
- [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
|
||||
- [`auto-changelog`](https://github.com/CookPete/auto-changelog)
|
||||
|
||||
## [v1.45.0](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
|
||||
## [v1.45.1](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
|
||||
|
||||
### Changes
|
||||
|
||||
|
|
|
@ -5,12 +5,17 @@ Overview of the commands to test, run and build this project as well as those th
|
|||
## Most important commands for development
|
||||
|
||||
- `npm install` Installs all dependencies and creates the folder `node_modules`, that is needed for all following commands.
|
||||
- `npm run lint` Lint src/ and test/ codebase (using ESLint)
|
||||
- `npm run format` Pretty src/ and test/ codebase (using Prettier)
|
||||
- `npm run inspect` Check src/ and test/ codebase (using TSC and ESLint)
|
||||
- `npm run changelog` Update CHANGELOG.md
|
||||
- `npm login` + `npm publish` To publish a new release. Be sure to run npm run package first.
|
||||
|
||||
## Commands to test, run and build the project
|
||||
|
||||
- `npm test` Run all unit tests (using Jest) with reporting coverage
|
||||
- `npm test` or `npm run test:unit` Run all unit tests (using Jest) with reporting coverage
|
||||
- `npm test:perf` Run all performance tests (using Benchmark.js) with reporting results
|
||||
- `npm run test:perf -- priority-queue.test` Run specific performance test
|
||||
|
||||
[//]: # (- `npm run coverage-badge` Updates code coverage badge inside `README.md`)
|
||||
- `npm run build:docs` Generates JSDoc Documentation in folder "docs"
|
||||
|
|
33
README.md
33
README.md
|
@ -734,50 +734,53 @@ optimal approach to data structure design.
|
|||
|
||||
[//]: # (No deletion!!! Start of Replace Section)
|
||||
<div class="json-to-html-collapse clearfix 0">
|
||||
<div class='collapsible level0' ><span class='json-to-html-label'>comparation</span></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>SRC 10,000 add</td><td>0.59</td><td>1701.78</td><td>3.28e-5</td></tr><tr><td>CJS 10,000 add</td><td>0.61</td><td>1648.70</td><td>6.98e-5</td></tr><tr><td>MJS 10,000 add</td><td>0.59</td><td>1691.86</td><td>2.44e-5</td></tr><tr><td>SRC PQ 10,000 add & pop</td><td>4.97</td><td>201.19</td><td>1.37e-4</td></tr><tr><td>CJS PQ 10,000 add & pop</td><td>4.93</td><td>202.70</td><td>5.60e-5</td></tr><tr><td>MJS PQ 10,000 add & pop</td><td>4.98</td><td>200.74</td><td>4.39e-4</td></tr></table></div>
|
||||
</div><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 style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add randomly</td><td>33.34</td><td>29.99</td><td>0.00</td></tr><tr><td>10,000 add & delete randomly</td><td>72.30</td><td>13.83</td><td>0.00</td></tr><tr><td>10,000 addMany</td><td>49.50</td><td>20.20</td><td>0.00</td></tr><tr><td>10,000 get</td><td>27.23</td><td>36.73</td><td>7.19e-4</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add randomly</td><td>32.27</td><td>30.99</td><td>0.00</td></tr><tr><td>10,000 add & delete randomly</td><td>73.67</td><td>13.57</td><td>0.00</td></tr><tr><td>10,000 addMany</td><td>41.81</td><td>23.92</td><td>0.00</td></tr><tr><td>10,000 get</td><td>29.21</td><td>34.24</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 style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000 add randomly</td><td>12.20</td><td>81.97</td><td>8.36e-5</td></tr><tr><td>1,000 add & delete randomly</td><td>15.93</td><td>62.77</td><td>2.09e-4</td></tr><tr><td>1,000 addMany</td><td>10.36</td><td>96.56</td><td>2.01e-4</td></tr><tr><td>1,000 get</td><td>18.43</td><td>54.26</td><td>4.67e-4</td></tr><tr><td>1,000 dfs</td><td>154.61</td><td>6.47</td><td>0.00</td></tr><tr><td>1,000 bfs</td><td>57.73</td><td>17.32</td><td>0.01</td></tr><tr><td>1,000 morris</td><td>258.47</td><td>3.87</td><td>0.00</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000 add randomly</td><td>13.82</td><td>72.38</td><td>0.00</td></tr><tr><td>1,000 add & delete randomly</td><td>16.01</td><td>62.45</td><td>5.80e-4</td></tr><tr><td>1,000 addMany</td><td>12.30</td><td>81.33</td><td>0.01</td></tr><tr><td>1,000 get</td><td>19.75</td><td>50.63</td><td>0.01</td></tr><tr><td>1,000 dfs</td><td>157.12</td><td>6.36</td><td>0.00</td></tr><tr><td>1,000 bfs</td><td>56.72</td><td>17.63</td><td>4.27e-4</td></tr><tr><td>1,000 morris</td><td>334.97</td><td>2.99</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'>bst</span></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add randomly</td><td>29.44</td><td>33.96</td><td>3.99e-4</td></tr><tr><td>10,000 add & delete randomly</td><td>72.35</td><td>13.82</td><td>0.00</td></tr><tr><td>10,000 addMany</td><td>29.76</td><td>33.60</td><td>0.00</td></tr><tr><td>10,000 get</td><td>28.53</td><td>35.05</td><td>5.76e-4</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add randomly</td><td>28.30</td><td>35.34</td><td>0.00</td></tr><tr><td>10,000 add & delete randomly</td><td>67.47</td><td>14.82</td><td>0.00</td></tr><tr><td>10,000 addMany</td><td>29.25</td><td>34.18</td><td>0.00</td></tr><tr><td>10,000 get</td><td>30.53</td><td>32.75</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'>rb-tree</span></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>90.42</td><td>11.06</td><td>0.01</td></tr><tr><td>100,000 add & delete randomly</td><td>223.52</td><td>4.47</td><td>0.02</td></tr><tr><td>100,000 getNode</td><td>38.67</td><td>25.86</td><td>0.00</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>96.67</td><td>10.34</td><td>0.01</td></tr><tr><td>100,000 add & delete randomly</td><td>224.85</td><td>4.45</td><td>0.01</td></tr><tr><td>100,000 getNode</td><td>40.83</td><td>24.49</td><td>2.73e-4</td></tr></table></div>
|
||||
</div><div class="json-to-html-collapse clearfix 0">
|
||||
<div class='collapsible level0' ><span class='json-to-html-label'>directed-graph</span></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000 addVertex</td><td>0.11</td><td>9499.56</td><td>5.09e-6</td></tr><tr><td>1,000 addEdge</td><td>6.37</td><td>157.04</td><td>8.13e-4</td></tr><tr><td>1,000 getVertex</td><td>0.05</td><td>2.15e+4</td><td>1.20e-6</td></tr><tr><td>1,000 getEdge</td><td>22.44</td><td>44.56</td><td>0.00</td></tr><tr><td>tarjan</td><td>213.53</td><td>4.68</td><td>0.01</td></tr><tr><td>tarjan all</td><td>215.75</td><td>4.63</td><td>0.00</td></tr><tr><td>topologicalSort</td><td>175.51</td><td>5.70</td><td>0.01</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000 addVertex</td><td>0.11</td><td>9364.63</td><td>1.25e-5</td></tr><tr><td>1,000 addEdge</td><td>6.18</td><td>161.78</td><td>1.26e-4</td></tr><tr><td>1,000 getVertex</td><td>0.05</td><td>2.12e+4</td><td>4.19e-6</td></tr><tr><td>1,000 getEdge</td><td>25.98</td><td>38.50</td><td>0.01</td></tr><tr><td>tarjan</td><td>240.23</td><td>4.16</td><td>0.02</td></tr><tr><td>tarjan all</td><td>227.36</td><td>4.40</td><td>0.00</td></tr><tr><td>topologicalSort</td><td>185.85</td><td>5.38</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'>hash-map</span></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 set</td><td>0.76</td><td>1308.63</td><td>1.65e-5</td></tr><tr><td>10,000 set & get</td><td>1.03</td><td>966.59</td><td>2.21e-5</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 set</td><td>1.00</td><td>1001.31</td><td>1.82e-5</td></tr><tr><td>10,000 set & get</td><td>1.54</td><td>650.14</td><td>4.87e-5</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 style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add & pop</td><td>4.65</td><td>214.92</td><td>1.18e-4</td></tr><tr><td>10,000 fib add & pop</td><td>367.35</td><td>2.72</td><td>0.01</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add & pop</td><td>6.97</td><td>143.49</td><td>5.27e-4</td></tr><tr><td>10,000 fib add & pop</td><td>378.40</td><td>2.64</td><td>0.05</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 style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 unshift</td><td>222.80</td><td>4.49</td><td>0.06</td></tr><tr><td>1,000,000 unshift & shift</td><td>174.60</td><td>5.73</td><td>0.04</td></tr><tr><td>1,000,000 insertBefore</td><td>309.21</td><td>3.23</td><td>0.07</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 unshift</td><td>224.55</td><td>4.45</td><td>0.07</td></tr><tr><td>1,000,000 unshift & shift</td><td>182.17</td><td>5.49</td><td>0.06</td></tr><tr><td>1,000,000 insertBefore</td><td>342.63</td><td>2.92</td><td>0.08</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 style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 push & pop</td><td>214.75</td><td>4.66</td><td>0.01</td></tr><tr><td>10,000 insertBefore</td><td>250.45</td><td>3.99</td><td>0.01</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 push & pop</td><td>222.42</td><td>4.50</td><td>0.01</td></tr><tr><td>10,000 insertBefore</td><td>248.39</td><td>4.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'>max-priority-queue</span></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 refill & poll</td><td>11.44</td><td>87.43</td><td>1.80e-4</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 refill & poll</td><td>11.83</td><td>84.55</td><td>1.45e-4</td></tr></table></div>
|
||||
</div><div class="json-to-html-collapse clearfix 0">
|
||||
<div class='collapsible level0' ><span class='json-to-html-label'>priority-queue</span></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add & pop</td><td>12.41</td><td>80.57</td><td>1.56e-4</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add & pop</td><td>10.79</td><td>92.72</td><td>2.01e-4</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 style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>219.15</td><td>4.56</td><td>0.04</td></tr><tr><td>1,000,000 shift</td><td>26.76</td><td>37.37</td><td>0.00</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>231.33</td><td>4.32</td><td>0.06</td></tr><tr><td>1,000,000 shift</td><td>27.64</td><td>36.17</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'>queue</span></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>45.17</td><td>22.14</td><td>0.01</td></tr><tr><td>1,000,000 push & shift</td><td>80.41</td><td>12.44</td><td>0.00</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>46.16</td><td>21.66</td><td>0.01</td></tr><tr><td>1,000,000 push & shift</td><td>82.18</td><td>12.17</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'>stack</span></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>43.67</td><td>22.90</td><td>0.01</td></tr><tr><td>1,000,000 push & pop</td><td>48.18</td><td>20.76</td><td>0.00</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>45.45</td><td>22.00</td><td>0.01</td></tr><tr><td>1,000,000 push & pop</td><td>50.10</td><td>19.96</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'>trie</span></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 push</td><td>60.46</td><td>16.54</td><td>0.00</td></tr><tr><td>100,000 getWords</td><td>83.13</td><td>12.03</td><td>0.00</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 push</td><td>46.25</td><td>21.62</td><td>0.00</td></tr><tr><td>100,000 getWords</td><td>65.17</td><td>15.34</td><td>0.00</td></tr></table></div>
|
||||
</div>
|
||||
|
||||
[//]: # (No deletion!!! End of Replace Section)
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "data-structure-typed",
|
||||
"version": "1.45.0",
|
||||
"version": "1.45.2",
|
||||
"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",
|
||||
|
|
|
@ -305,18 +305,28 @@ export class Heap<E = any> {
|
|||
* @param index - The index of the newly added element.
|
||||
*/
|
||||
protected bubbleUp(index: number): void {
|
||||
const element = this.nodes[index];
|
||||
// const element = this.nodes[index];
|
||||
// while (index > 0) {
|
||||
// const parentIndex = (index - 1) >> 1;
|
||||
// const parent = this.nodes[parentIndex];
|
||||
// if (this.comparator(element, parent) < 0) {
|
||||
// this.nodes[index] = parent;
|
||||
// this.nodes[parentIndex] = element;
|
||||
// index = parentIndex;
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
const item = this.nodes[index];
|
||||
while (index > 0) {
|
||||
const parentIndex = Math.floor((index - 1) / 2);
|
||||
const parent = this.nodes[parentIndex];
|
||||
if (this.comparator(element, parent) < 0) {
|
||||
this.nodes[index] = parent;
|
||||
this.nodes[parentIndex] = element;
|
||||
index = parentIndex;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
const parent = (index - 1) >> 1;
|
||||
const parentItem = this.nodes[parent];
|
||||
if (this.comparator(parentItem, item) <= 0) break;
|
||||
this.nodes[index] = parentItem;
|
||||
index = parent;
|
||||
}
|
||||
this.nodes[index] = item;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -332,8 +342,8 @@ export class Heap<E = any> {
|
|||
* @param index - The index from which to start sinking.
|
||||
*/
|
||||
protected sinkDown(index: number): void {
|
||||
const leftChildIndex = 2 * index + 1;
|
||||
const rightChildIndex = 2 * index + 2;
|
||||
const leftChildIndex = index << 1 | 1;
|
||||
const rightChildIndex = leftChildIndex + 1;
|
||||
const length = this.nodes.length;
|
||||
let targetIndex = index;
|
||||
|
||||
|
@ -774,3 +784,117 @@ export class FibonacciHeap<E> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class CHeap<T> {
|
||||
|
||||
protected _length = 0;
|
||||
private readonly _priorityQueue: T[] = [];
|
||||
private readonly _cmp: (x: T, y: T) => number;
|
||||
|
||||
constructor(
|
||||
cmp: (x: T, y: T) => number =
|
||||
function (x: T, y: T) {
|
||||
if (x > y) return -1;
|
||||
if (x < y) return 1;
|
||||
return 0;
|
||||
},
|
||||
copy = true
|
||||
) {
|
||||
|
||||
this._cmp = cmp;
|
||||
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._length = 0;
|
||||
this._priorityQueue.length = 0;
|
||||
}
|
||||
|
||||
push(item: T) {
|
||||
this._priorityQueue.push(item);
|
||||
this._pushUp(this._length);
|
||||
this._length += 1;
|
||||
}
|
||||
|
||||
pop() {
|
||||
if (this._length === 0) return;
|
||||
const value = this._priorityQueue[0];
|
||||
const last = this._priorityQueue.pop()!;
|
||||
this._length -= 1;
|
||||
if (this._length) {
|
||||
this._priorityQueue[0] = last;
|
||||
this._pushDown(0, this._length >> 1);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
top(): T | undefined {
|
||||
return this._priorityQueue[0];
|
||||
}
|
||||
|
||||
find(item: T) {
|
||||
return this._priorityQueue.indexOf(item) >= 0;
|
||||
}
|
||||
|
||||
remove(item: T) {
|
||||
const index = this._priorityQueue.indexOf(item);
|
||||
if (index < 0) return false;
|
||||
if (index === 0) {
|
||||
this.pop();
|
||||
} else if (index === this._length - 1) {
|
||||
this._priorityQueue.pop();
|
||||
this._length -= 1;
|
||||
} else {
|
||||
this._priorityQueue.splice(index, 1, this._priorityQueue.pop()!);
|
||||
this._length -= 1;
|
||||
this._pushUp(index);
|
||||
this._pushDown(index, this._length >> 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
updateItem(item: T) {
|
||||
const index = this._priorityQueue.indexOf(item);
|
||||
if (index < 0) return false;
|
||||
this._pushUp(index);
|
||||
this._pushDown(index, this._length >> 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
toArray() {
|
||||
return [...this._priorityQueue];
|
||||
}
|
||||
|
||||
private _pushUp(pos: number) {
|
||||
const item = this._priorityQueue[pos];
|
||||
while (pos > 0) {
|
||||
const parent = (pos - 1) >> 1;
|
||||
const parentItem = this._priorityQueue[parent];
|
||||
if (this._cmp(parentItem, item) <= 0) break;
|
||||
this._priorityQueue[pos] = parentItem;
|
||||
pos = parent;
|
||||
}
|
||||
this._priorityQueue[pos] = item;
|
||||
}
|
||||
|
||||
private _pushDown(pos: number, halfLength: number) {
|
||||
const item = this._priorityQueue[pos];
|
||||
while (pos < halfLength) {
|
||||
let left = pos << 1 | 1;
|
||||
const right = left + 1;
|
||||
let minItem = this._priorityQueue[left];
|
||||
if (
|
||||
right < this._length &&
|
||||
this._cmp(minItem, this._priorityQueue[right]) > 0
|
||||
) {
|
||||
left = right;
|
||||
minItem = this._priorityQueue[right];
|
||||
}
|
||||
if (this._cmp(minItem, item) >= 0) break;
|
||||
this._priorityQueue[pos] = minItem;
|
||||
pos = left;
|
||||
}
|
||||
this._priorityQueue[pos] = item;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ const suite = new Benchmark.Suite();
|
|||
const rbTree = new RedBlackTree();
|
||||
const { HUNDRED_THOUSAND } = magnitude;
|
||||
const arr = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSAND, true);
|
||||
const competitor = new OrderedMap<number, number>();
|
||||
const cOrderedMap = new OrderedMap<number, number>();
|
||||
|
||||
suite.add(`${HUNDRED_THOUSAND.toLocaleString()} add`, () => {
|
||||
rbTree.clear();
|
||||
|
@ -18,9 +18,9 @@ suite.add(`${HUNDRED_THOUSAND.toLocaleString()} add`, () => {
|
|||
});
|
||||
|
||||
if (isCompetitor) {
|
||||
suite.add(`${HUNDRED_THOUSAND.toLocaleString()} competitor add`, () => {
|
||||
suite.add(`${HUNDRED_THOUSAND.toLocaleString()} CPT add`, () => {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
competitor.setElement(arr[i], arr[i]);
|
||||
cOrderedMap.setElement(arr[i], arr[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
142
test/performance/data-structures/comparation.test.ts
Normal file
142
test/performance/data-structures/comparation.test.ts
Normal file
|
@ -0,0 +1,142 @@
|
|||
import { PriorityQueue as MJSPriorityQueue } from '../../../dist/cjs';
|
||||
import { PriorityQueue as SRCPriorityQueue } from '../../../src';
|
||||
import { PriorityQueue as CJSPriorityQueue } from '../../../dist/mjs';
|
||||
import {
|
||||
Deque as CDeque,
|
||||
HashMap as CHashMap,
|
||||
LinkList as CLinkedList,
|
||||
OrderedMap,
|
||||
PriorityQueue as CPriorityQueue,
|
||||
Queue as CQueue,
|
||||
Stack as CStack
|
||||
} from 'js-sdsl';
|
||||
|
||||
import * as Benchmark from 'benchmark';
|
||||
import { getRandomIntArray, magnitude } from '../../utils';
|
||||
import { isCompetitor } from '../../config';
|
||||
|
||||
const suite = new Benchmark.Suite();
|
||||
const { TEN_THOUSAND, HUNDRED_THOUSAND, LINEAR } = magnitude;
|
||||
const cOrderedMap = new OrderedMap<number, number>();
|
||||
const arrHundredThousand = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSAND, true);
|
||||
|
||||
suite.add(`SRC ${TEN_THOUSAND.toLocaleString()} add`, () => {
|
||||
|
||||
const pq = new SRCPriorityQueue<number>({ comparator: (a, b) => b - a });
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.add(i);
|
||||
}).add(`CJS ${TEN_THOUSAND.toLocaleString()} add`, () => {
|
||||
|
||||
const pq = new CJSPriorityQueue<number>({ comparator: (a, b) => b - a });
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.add(i);
|
||||
}).add(`MJS ${TEN_THOUSAND.toLocaleString()} add`, () => {
|
||||
|
||||
const pq = new MJSPriorityQueue<number>({ comparator: (a, b) => b - a });
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.add(i);
|
||||
});
|
||||
|
||||
if (isCompetitor) {
|
||||
suite.add(`CPT PQ ${TEN_THOUSAND.toLocaleString()} add`, () => {
|
||||
|
||||
const pq = new CPriorityQueue<number>();
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.push(i);
|
||||
});
|
||||
}
|
||||
|
||||
suite.add(`SRC PQ ${TEN_THOUSAND.toLocaleString()} add & pop`, () => {
|
||||
const pq = new SRCPriorityQueue<number>({ comparator: (a, b) => b - a });
|
||||
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.add(i);
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.pop();
|
||||
}).add(`CJS PQ ${TEN_THOUSAND.toLocaleString()} add & pop`, () => {
|
||||
const pq = new CJSPriorityQueue<number>({ comparator: (a, b) => b - a });
|
||||
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.add(i);
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.pop();
|
||||
}).add(`MJS PQ ${TEN_THOUSAND.toLocaleString()} add & pop`, () => {
|
||||
const pq = new MJSPriorityQueue<number>({ comparator: (a, b) => b - a });
|
||||
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.add(i);
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.pop();
|
||||
});
|
||||
|
||||
|
||||
if (isCompetitor) {
|
||||
suite.add(`CPT PQ ${TEN_THOUSAND.toLocaleString()} add & pop`, () => {
|
||||
const pq = new CPriorityQueue<number>();
|
||||
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.push(i);
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.pop();
|
||||
})
|
||||
.add(`CPT OM ${HUNDRED_THOUSAND.toLocaleString()} add`, () => {
|
||||
for (let i = 0; i < arrHundredThousand.length; i++) {
|
||||
cOrderedMap.setElement(arrHundredThousand[i], arrHundredThousand[i]);
|
||||
}
|
||||
})
|
||||
.add(`CPT HM ${TEN_THOUSAND.toLocaleString()} set`, () => {
|
||||
const hm = new CHashMap<number, number>();
|
||||
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) {
|
||||
hm.setElement(i, i);
|
||||
}
|
||||
})
|
||||
.add(`CPT HM ${TEN_THOUSAND.toLocaleString()} set & get`, () => {
|
||||
const hm = new CHashMap<number, number>();
|
||||
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) {
|
||||
hm.setElement(i, i);
|
||||
}
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) {
|
||||
hm.getElementByKey(i);
|
||||
}
|
||||
})
|
||||
.add(`CPT LL ${LINEAR.toLocaleString()} unshift`, () => {
|
||||
const list = new CLinkedList<number>();
|
||||
|
||||
for (let i = 0; i < LINEAR; i++) {
|
||||
list.pushFront(i);
|
||||
}
|
||||
})
|
||||
.add(`CPT PQ ${TEN_THOUSAND.toLocaleString()} add & pop`, () => {
|
||||
const pq = new CPriorityQueue<number>();
|
||||
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) {
|
||||
pq.push(i);
|
||||
}
|
||||
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) {
|
||||
pq.pop();
|
||||
}
|
||||
})
|
||||
.add(`CPT DQ ${LINEAR.toLocaleString()} push`, () => {
|
||||
const deque = new CDeque<number>();
|
||||
for (let i = 0; i < LINEAR; i++) {
|
||||
deque.pushBack(i);
|
||||
}
|
||||
})
|
||||
.add(`CPT Q ${LINEAR.toLocaleString()} push`, () => {
|
||||
const queue = new CQueue<number>();
|
||||
|
||||
for (let i = 0; i < LINEAR; i++) {
|
||||
queue.push(i);
|
||||
}
|
||||
})
|
||||
.add(`CPT ST ${LINEAR.toLocaleString()} push`, () => {
|
||||
const queue = new CStack<number>();
|
||||
|
||||
for (let i = 0; i < LINEAR; i++) {
|
||||
queue.push(i);
|
||||
}
|
||||
})
|
||||
.add(`CPT ST ${LINEAR.toLocaleString()} push & pop`, () => {
|
||||
const queue = new CStack<number>();
|
||||
|
||||
for (let i = 0; i < LINEAR; i++) {
|
||||
queue.push(i);
|
||||
}
|
||||
for (let i = 0; i < LINEAR; i++) {
|
||||
queue.pop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export { suite };
|
|
@ -15,7 +15,7 @@ suite.add(`${TEN_THOUSAND.toLocaleString()} set`, () => {
|
|||
}
|
||||
});
|
||||
if (isCompetitor) {
|
||||
suite.add(`${TEN_THOUSAND.toLocaleString()} competitor set`, () => {
|
||||
suite.add(`${TEN_THOUSAND.toLocaleString()} CPT set`, () => {
|
||||
const hm = new CHashMap<number, number>();
|
||||
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) {
|
||||
|
@ -34,7 +34,7 @@ suite.add(`${TEN_THOUSAND.toLocaleString()} set & get`, () => {
|
|||
}
|
||||
});
|
||||
if (isCompetitor) {
|
||||
suite.add(`${TEN_THOUSAND.toLocaleString()} competitor set & get`, () => {
|
||||
suite.add(`${TEN_THOUSAND.toLocaleString()} CPT set & get`, () => {
|
||||
const hm = new CHashMap<number, number>();
|
||||
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) {
|
||||
|
|
|
@ -15,7 +15,7 @@ suite.add(`${LINEAR.toLocaleString()} unshift`, () => {
|
|||
}
|
||||
});
|
||||
if (isCompetitor) {
|
||||
suite.add(`${LINEAR.toLocaleString()} competitor unshift`, () => {
|
||||
suite.add(`${LINEAR.toLocaleString()} CPT unshift`, () => {
|
||||
const list = new CLinkedList<number>();
|
||||
|
||||
for (let i = 0; i < LINEAR; i++) {
|
||||
|
|
|
@ -19,7 +19,7 @@ suite.add(`${TEN_THOUSAND.toLocaleString()} add & pop`, () => {
|
|||
}
|
||||
});
|
||||
if (isCompetitor) {
|
||||
suite.add(`${TEN_THOUSAND.toLocaleString()} competitor add & pop`, () => {
|
||||
suite.add(`${TEN_THOUSAND.toLocaleString()} CPT add & pop`, () => {
|
||||
const pq = new CPriorityQueue<number>();
|
||||
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) {
|
||||
|
|
|
@ -14,7 +14,7 @@ suite.add(`${LINEAR.toLocaleString()} push`, () => {
|
|||
}
|
||||
});
|
||||
if (isCompetitor) {
|
||||
suite.add(`${LINEAR.toLocaleString()} competitor push`, () => {
|
||||
suite.add(`${LINEAR.toLocaleString()} CPT push`, () => {
|
||||
const deque = new CDeque<number>();
|
||||
for (let i = 0; i < LINEAR; i++) {
|
||||
deque.pushBack(i);
|
||||
|
|
|
@ -15,7 +15,7 @@ suite.add(`${LINEAR.toLocaleString()} push`, () => {
|
|||
}
|
||||
});
|
||||
if (isCompetitor) {
|
||||
suite.add(`${LINEAR.toLocaleString()} competitor push`, () => {
|
||||
suite.add(`${LINEAR.toLocaleString()} CPT push`, () => {
|
||||
const queue = new CQueue<number>();
|
||||
|
||||
for (let i = 0; i < LINEAR; i++) {
|
||||
|
|
|
@ -15,7 +15,7 @@ suite.add(`${LINEAR.toLocaleString()} push`, () => {
|
|||
}
|
||||
});
|
||||
if (isCompetitor) {
|
||||
suite.add(`${LINEAR.toLocaleString()} competitor push`, () => {
|
||||
suite.add(`${LINEAR.toLocaleString()} CPT push`, () => {
|
||||
const queue = new CStack<number>();
|
||||
|
||||
for (let i = 0; i < LINEAR; i++) {
|
||||
|
@ -34,7 +34,7 @@ suite.add(`${LINEAR.toLocaleString()} push & pop`, () => {
|
|||
}
|
||||
});
|
||||
if (isCompetitor) {
|
||||
suite.add(`${LINEAR.toLocaleString()} competitor push & pop`, () => {
|
||||
suite.add(`${LINEAR.toLocaleString()} CPT push & pop`, () => {
|
||||
const queue = new CStack<number>();
|
||||
|
||||
for (let i = 0; i < LINEAR; i++) {
|
||||
|
|
|
@ -5,18 +5,46 @@ import * as fastGlob from 'fast-glob';
|
|||
import { Color, numberFix, render } from '../utils';
|
||||
import { PerformanceTest } from './types';
|
||||
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
const { GREEN, BOLD, END, YELLOW, GRAY, CYAN, BG_YELLOW } = Color;
|
||||
|
||||
const getRelativePath = (file: string) => {
|
||||
return path.relative(__dirname, file);
|
||||
}
|
||||
const coloredLabeled = (label: string, file: string) => {
|
||||
const relativeFilePath = getRelativePath(file);
|
||||
const directory = path.dirname(relativeFilePath);
|
||||
const fileName = path.basename(relativeFilePath);
|
||||
return `${BG_YELLOW} ${label} ${END} ${GRAY}${directory}/${END}${CYAN}${fileName}${END}`;
|
||||
}
|
||||
|
||||
const parentDirectory = path.resolve(__dirname, '../..');
|
||||
const reportDistPath = path.join(parentDirectory, 'benchmark');
|
||||
|
||||
const testDir = path.join(__dirname, 'data-structures');
|
||||
const testFiles = fastGlob.sync(path.join(testDir, '**', '*.test.ts'));
|
||||
const allFiles = fastGlob.sync(path.join(testDir, '**', '*.test.ts'));
|
||||
let testFiles: string[] = [];
|
||||
if (args.length > 0) {
|
||||
console.log(`arguments: ${args.join(' ')}`)
|
||||
|
||||
testFiles = allFiles.filter(file =>
|
||||
args.every(word => file.includes(word))
|
||||
);
|
||||
|
||||
console.log(`${testFiles.map(file => coloredLabeled('Matched', file)).join(`
|
||||
`)}`);
|
||||
} else {
|
||||
testFiles = allFiles;
|
||||
}
|
||||
|
||||
|
||||
const report: { [key: string]: any } = {};
|
||||
|
||||
let completedCount = 0;
|
||||
|
||||
const performanceTests: PerformanceTest[] = [];
|
||||
const { GREEN, BOLD, END, YELLOW, GRAY, CYAN, BG_YELLOW } = Color;
|
||||
|
||||
testFiles.forEach((file: string) => {
|
||||
const testName = path.basename(file, '.test.ts');
|
||||
|
@ -107,7 +135,7 @@ const composeReport = () => {
|
|||
htmlTables // New content to be inserted
|
||||
);
|
||||
fs.writeFileSync(htmlFilePath, html);
|
||||
console.log(`Performance ${BOLD}${GREEN}report${END} file generated in ${BOLD}${GREEN}${reportDistPath}${END}`);
|
||||
console.log(`Performance ${BOLD}${GREEN}report${END} file generated in file://${BOLD}${GREEN}${htmlFilePath}${END}`);
|
||||
};
|
||||
|
||||
function replaceMarkdownContent(startMarker: string, endMarker: string, newText: string) {
|
||||
|
@ -135,7 +163,7 @@ function replaceMarkdownContent(startMarker: string, endMarker: string, newText:
|
|||
if (err) {
|
||||
console.error(`Unable to write to ${filePath}:`, err);
|
||||
} else {
|
||||
console.log(`The content has been successfully replaced in ${BOLD}${GREEN}${filePath}!${END}`);
|
||||
console.log(`The content has been successfully replaced in file://${BOLD}${GREEN}${filePath}${END}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -143,10 +171,8 @@ function replaceMarkdownContent(startMarker: string, endMarker: string, newText:
|
|||
|
||||
performanceTests.forEach(item => {
|
||||
const { suite, testName, file } = item;
|
||||
const relativeFilePath = path.relative(__dirname, file);
|
||||
const directory = path.dirname(relativeFilePath);
|
||||
const fileName = path.basename(relativeFilePath);
|
||||
console.log(`${BG_YELLOW} Running ${END} ${GRAY}${directory}/${END}${CYAN}${fileName}${END}`);
|
||||
|
||||
console.log(coloredLabeled('Running', file));
|
||||
|
||||
if (suite) {
|
||||
let runTime = 0;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { FibonacciHeap, MaxHeap, MinHeap } from '../../../../src';
|
||||
import { logBigOMetricsWrap } from '../../../utils';
|
||||
import { CHeap, FibonacciHeap, MaxHeap, MinHeap } from '../../../../src';
|
||||
import { calcRunTime, logBigOMetricsWrap } from '../../../utils';
|
||||
|
||||
describe('Heap Operation Test', () => {
|
||||
it('should numeric heap work well', function () {
|
||||
|
@ -257,3 +257,41 @@ describe('FibonacciHeap Stress Test', () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
// describe('Competitor performance compare', () => {
|
||||
// const minHeap = new MinHeap<number>();
|
||||
// const cHeap = new CHeap<number>();
|
||||
// const cPQ = new PriorityQueue<number>(undefined, (a, b) => a - b);
|
||||
// const n = 10000;
|
||||
//
|
||||
// it('should add performance well', () => {
|
||||
// const heapCost = calcRunTime(() => {
|
||||
// for (let i = 0; i < n; i++) {
|
||||
// minHeap.add(i);
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// console.log(`heapCost: ${heapCost}`)
|
||||
// });
|
||||
//
|
||||
// it('should add performance well', () => {
|
||||
//
|
||||
// const cHeapCost = calcRunTime(() => {
|
||||
// for (let i = 0; i < n; i++) {
|
||||
// cHeap.push(i);
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// console.log(`cHeapCost: ${cHeapCost}`)
|
||||
// });
|
||||
//
|
||||
// it('should add performance well', () => {
|
||||
//
|
||||
// const cPQCost = calcRunTime(() => {
|
||||
// for (let i = 0; i < n; i++) {
|
||||
// cPQ.push(i);
|
||||
// }
|
||||
// })
|
||||
// console.log(`cPQCost: ${cPQCost}`)
|
||||
// });
|
||||
// });
|
||||
|
|
|
@ -5,3 +5,4 @@ export * from './json2html';
|
|||
export * from './is';
|
||||
export * from './console';
|
||||
export * from './string';
|
||||
export * from './performanc';
|
||||
|
|
7
test/utils/performanc.ts
Normal file
7
test/utils/performanc.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { performance } from 'perf_hooks';
|
||||
|
||||
export const calcRunTime = (callback: (...args: any[]) => any) => {
|
||||
const startTime = performance.now();
|
||||
callback();
|
||||
return performance.now() - startTime;
|
||||
}
|
Loading…
Reference in a new issue