Understand how data-structure-typed performs, and when to use each structure.
Back to README β’ Architecture Details β’ Code Examples β’ π Interactive HTML Report
Table of Contentsβ
- Performance Summary
- Real-World Scenarios
- Detailed Benchmarks
- When to Use What
- Optimization Tips
Note on JS vs C++ gaps: Many βC++ fasterβ results are primarily explained by runtime / memory-model differences, not a flaw in data-structure-typed.
JavaScript runs on a GCβd VM with boxed numbers, dynamic dispatch, and different cache/memory behavior, while C++ can use tight value types and predictable memory layouts.
When the benchmark mixes in baseline containers (Native JS / js-sdsl / C++), treat cross-language comparisons as directional and rely most on within-JS comparisons for practical decisions.
Key Numbersβ
- 484x faster than Array.shift() with 100K elements (Deque vs Array)
- 40xβ308x faster in repeated βupdate + resortβ workloads (RedBlackTree vs Array)
- O(log n) guaranteed on all balanced tree operations
- O(1) guaranteed on Deque head/tail operations
- Benchmarks include warm-up runs to reduce V8 JIT noise
| Structure | Access | Search | Insert | Delete | Best For |
|---|
| Array | O(1) | O(n) | O(n) | O(n) | Random access |
| LinkedList | O(n) | O(n) | O(1)* | O(1)* | If you have pointer |
| Stack | - | - | O(1) | O(1) | LIFO, undo/redo |
| Queue | - | - | O(1) | O(1) | FIFO, message queues |
| Deque | - | - | O(1) | O(1) | Head/tail ops |
| BST | O(log n) | O(log n) | O(log n) | O(log n) | Sorted if balanced |
| RedBlackTree | O(log n) | O(log n) | O(log n) | O(log n) | Guaranteed sorted |
| AVL Tree | O(log n) | O(log n) | O(log n) | O(log n) | Max search speed |
| Heap | O(n) | O(n) | O(log n) | O(log n) | Priority queue |
| Trie | N/A | O(m) | O(m) | O(m) | Prefix search |
Benchmarkβ
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 1M push | 26.93 | 24.41 | 51.97 | Β±4.28% |
| 100K push & shift | 3.45 | 2.72 | 15.26 | Β±8.97% |
Queue (side-by-side)β
Comparison table. The main table above is Queue only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 1M push | 26.93 | 23.83 | 1.70 | 27.59 |
| 100K push & shift | 3.45 | 1152.77 | 0.20 | 2.71 |
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 1M push | 9.77 | 6.27 | 21.63 | Β±9.28% |
| 1M push & pop | 14.75 | 11.80 | 31.16 | Β±5.06% |
| 1M push & shift | 14.61 | 13.31 | 40.42 | Β±5.25% |
| 100K push & shift | 1.29 | 1.19 | 3.37 | Β±3.91% |
| 100K unshift & shift | 1.26 | 1.14 | 2.75 | Β±3.59% |
Deque (side-by-side)β
Comparison table. The main table above is Deque only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 1M push | 9.77 | 26.81 | 1.76 | 7.79 |
| 1M push & pop | 14.75 | 27.96 | 2.20 | 12.34 |
| 1M push & shift | 14.61 | - | 1.94 | - |
| 100K push & shift | 1.29 | 1243.77 | 0.19 | 1.17 |
| 100K unshift & shift | 1.26 | 1867.28 | 0.19 | 1.17 |
DoublyLinkedListβ
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 100k push | 5.70 | 4.80 | 7.27 | Β±1.57% |
| 100k unshift | 5.57 | 4.63 | 13.65 | Β±5.7% |
| 100k unshift & shift | 4.04 | 3.87 | 5.34 | Β±1.3% |
| 100k addAt(mid) | 1865.99 | 1778.94 | 1992.65 | Β±5.43% |
| 100k addBefore (cursor) | 6.81 | 5.32 | 17.77 | Β±4.44% |
DoublyLinkedList (side-by-side)β
Comparison table. The main table above is DoublyLinkedList only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 100k push | 5.70 | 2.40 | 5.70 | 1.90 |
| 100k unshift | 5.57 | 884.06 | 5.85 | 1.52 |
| 100k unshift & shift | 4.04 | 2050.71 | 5.74 | 1.89 |
| 100k addAt(mid) | 1865.99 | - | 754.81 | - |
| 100k addBefore (cursor) | 6.81 | - | 6.18 | - |
SinglyLinkedListβ
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 100K unshift & shift | 3.77 | 3.62 | 3.99 | Β±0.41% |
| 10K unshift & shift | 0.37 | 0.36 | 0.44 | Β±0.78% |
| 10K addAt(mid) | 18.61 | 17.61 | 25.55 | Β±1.66% |
| 10K addBefore (cursor) | 17.56 | 16.67 | 20.17 | Β±1.11% |
SinglyLinkedList (side-by-side)β
Comparison table. The main table above is SinglyLinkedList only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 100K unshift & shift | 3.77 | 1958.39 | 4.80 | - |
| 10K unshift & shift | 0.37 | 6.26 | 0.47 | - |
| 10K addAt(mid) | 18.61 | - | 5.77 | - |
| 10K addBefore (cursor) | 17.56 | - | 0.53 | - |
PriorityQueueβ
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 100K add | 4.00 | 3.80 | 4.41 | Β±0.6% |
| 100K add & poll | 22.51 | 21.23 | 42.99 | Β±3.19% |
PriorityQueue (side-by-side)β
Comparison table. The main table above is PriorityQueue only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 100K add | 4.00 | - | 1.05 | 4.96 |
| 100K add & poll | 22.51 | - | 4.53 | 22.97 |
TreeSetβ
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 1M add | 995.72 | 948.08 | 1124.92 | Β±6.28% |
| 1M has | 67.80 | 64.53 | 86.26 | Β±1.67% |
| 100K rangeSearch | 17.34 | 16.79 | 18.81 | Β±0.46% |
| 100K navigable | 118.65 | 117.95 | 119.38 | Β±0.14% |
TreeSet (side-by-side)β
Comparison table. The main table above is TreeSet only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | DST classic (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 1M add | 995.72 | 807.88 | - | 462.00 | 677.58 |
| 1M has | 67.80 | 747.62 | - | 444.00 | 655.62 |
| 100K rangeSearch | 17.34 | 16.70 | - | - | - |
| 100K navigable | 118.65 | 123.91 | - | - | - |
TreeMapβ
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 1M set | 978.72 | 934.59 | 1130.02 | Β±6.39% |
| 1M get | 127.82 | 123.10 | 133.96 | Β±1.2% |
| 100K rangeSearch | 38.17 | 34.80 | 100.14 | Β±6.97% |
| 100K navigable | 160.66 | 151.89 | 307.88 | Β±9.6% |
TreeMap (side-by-side)β
Comparison table. The main table above is TreeMap only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | DST classic (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 1M set | 978.72 | 831.32 | - | 512.00 | 623.23 |
| 1M get | 127.82 | 719.05 | - | 322.00 | 626.87 |
| 100K rangeSearch | 38.17 | 34.42 | - | - | - |
| 100K navigable | 160.66 | 213.76 | - | - | - |
TreeMultiSetβ
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 1M add (TreeMultiSet expanded iteration) | 217.73 | 191.17 | 319.78 | Β±8.07% |
| 1M has-only (TreeMultiSet) | 67.67 | 66.08 | 72.83 | Β±0.72% |
| 1M count-only (TreeMultiSet) | 55.74 | 53.94 | 57.60 | Β±0.49% |
| 1M build+has (TreeMultiSet) | 260.84 | 248.30 | 300.22 | Β±2.79% |
| 1M build+count (TreeMultiSet) | 267.81 | 242.77 | 339.53 | Β±5.97% |
| 100K delete-one (TreeMultiSet) | 217.76 | 201.92 | 254.80 | Β±2.97% |
| 100K setCount (TreeMultiSet) | 214.66 | 201.65 | 264.54 | Β±3.65% |
| 1M expanded iteration (TreeMultiSet) | 54.41 | 53.14 | 62.22 | Β±0.78% |
| 1M entries view (TreeMultiSet) | 15.67 | 14.81 | 17.19 | Β±0.72% |
| 1M size property (TreeMultiSet) | 0.00 | 0.00 | 0.00 | Β±3.47% |
| 1M distinctSize property (TreeMultiSet) | 0.00 | 0.00 | 0.00 | Β±3.88% |
TreeMultiSet (side-by-side)β
Comparison table. The main table above is TreeMultiSet only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 1M add (TreeMultiSet expanded iteration) | 217.73 | - | 752.00 | - |
| 1M has-only (TreeMultiSet) | 67.67 | - | 756.00 | - |
| 1M count-only (TreeMultiSet) | 55.74 | - | 1332.00 | - |
| 1M build+has (TreeMultiSet) | 260.84 | - | 1406.00 | - |
| 1M build+count (TreeMultiSet) | 267.81 | - | 1909.00 | - |
| 100K delete-one (TreeMultiSet) | 217.76 | - | - | - |
| 100K setCount (TreeMultiSet) | 214.66 | - | - | - |
| 1M expanded iteration (TreeMultiSet) | 54.41 | - | - | - |
| 1M entries view (TreeMultiSet) | 15.67 | - | - | - |
| 1M size property (TreeMultiSet) | 0.00 | - | - | - |
| 1M distinctSize property (TreeMultiSet) | 0.00 | - | - | - |
TreeMultiMapβ
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 1M add (TreeMultiMap bucketed) | 366.19 | 346.31 | 454.65 | Β±5.51% |
| 1M has-only (TreeMultiMap) | 35.37 | 34.94 | 36.94 | Β±0.39% |
| 1M get-only (TreeMultiMap) | 58.37 | 56.05 | 73.86 | Β±1.37% |
| 1M count-only (TreeMultiMap) | 105.34 | 94.16 | 124.54 | Β±2.71% |
| 1M build+has (TreeMultiMap) | 396.87 | 373.62 | 538.68 | Β±8.08% |
| 1M build+get (TreeMultiMap) | 416.59 | 412.46 | 424.84 | Β±0.62% |
| 100K hasEntry (TreeMultiMap Object.is) | 375.85 | 346.85 | 396.95 | Β±2.39% |
| 100K deleteValue (TreeMultiMap Object.is) | 411.69 | 388.10 | 577.77 | Β±9.06% |
| 100K firstEntry/lastEntry (TreeMultiMap) | 0.00 | - | - | Β±0% |
| 100K ceilingEntry/floorEntry (TreeMultiMap) | 0.00 | - | - | Β±0% |
| 1M bucket iteration (TreeMultiMap) | 22.55 | 21.91 | 25.20 | Β±0.68% |
| 1M flatEntries iteration (TreeMultiMap) | 106.47 | 104.33 | 110.52 | Β±0.6% |
| 1M size property (TreeMultiMap) | 0.00 | 0.00 | 0.00 | Β±4.08% |
| 1M totalSize property (TreeMultiMap) | 21.74 | 21.09 | 25.40 | Β±0.8% |
TreeMultiMap (side-by-side)β
Comparison table. The main table above is TreeMultiMap only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 1M add (TreeMultiMap bucketed) | 366.19 | - | 731.00 | - |
| 1M has-only (TreeMultiMap) | 35.37 | - | 833.00 | - |
| 1M get-only (TreeMultiMap) | 58.37 | - | 1553.00 | - |
| 1M count-only (TreeMultiMap) | 105.34 | - | 1548.00 | - |
| 1M build+has (TreeMultiMap) | 396.87 | - | 1519.00 | - |
| 1M build+get (TreeMultiMap) | 416.59 | - | 2263.00 | - |
| 100K hasEntry (TreeMultiMap Object.is) | 375.85 | - | - | - |
| 100K deleteValue (TreeMultiMap Object.is) | 411.69 | - | - | - |
| 100K firstEntry/lastEntry (TreeMultiMap) | 0.00 | - | - | - |
| 100K ceilingEntry/floorEntry (TreeMultiMap) | 0.00 | - | - | - |
| 1M bucket iteration (TreeMultiMap) | 22.55 | - | 109.00 | - |
| 1M flatEntries iteration (TreeMultiMap) | 106.47 | - | 109.00 | - |
| 1M size property (TreeMultiMap) | 0.00 | - | - | - |
| 1M totalSize property (TreeMultiMap) | 21.74 | - | - | - |
RedBlackTreeβ
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 1M get | 99.24 | 82.27 | 109.67 | Β±16.59% |
| 200K rangeSearch SEQ | 1365.15 | 1251.75 | 1491.01 | Β±9.18% |
| 200K rangeSearch RAND | 1565.26 | 1528.89 | 1613.47 | Β±2.69% |
| 1M upd SEQ | 84.75 | 82.26 | 86.85 | Β±3.10% |
| 1M upd RAND | 113.72 | 112.51 | 116.12 | Β±1.70% |
| 1M ins SEQ | 535.64 | 459.83 | 795.68 | Β±33.88% |
| 1M ins RAND | 989.88 | 973.81 | 1001.58 | Β±1.43% |
| 1M keys-only | 4.22 | 2.71 | 5.81 | Β±41.71% |
RedBlackTree (side-by-side)β
Comparison table. The main table above is RedBlackTree only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | DST classic (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 1M get | 99.24 | 304.72 | - | 52.97 | - |
| 200K rangeSearch SEQ | 1365.15 | - | - | - | - |
| 200K rangeSearch RAND | 1565.26 | - | - | - | - |
| 1M upd SEQ | 84.75 | 302.03 | - | 68.43 | - |
| 1M upd RAND | 113.72 | 422.53 | - | 158.14 | - |
| 1M ins SEQ | 535.64 | 211.38 | - | 162.72 | - |
| 1M ins RAND | 989.88 | 882.76 | - | 483.56 | - |
| 1M keys-only | 4.22 | - | - | 0.09 | - |
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 10K add randomly | 5.50 | 5.11 | 5.93 | Β±0.6% |
| 10K add & delete randomly | 10.01 | 9.75 | 10.79 | Β±0.4% |
| 10K addMany | 11.62 | 10.00 | 68.37 | Β±15.54% |
| 10K get | 10.65 | 10.35 | 11.67 | Β±0.48% |
BST (side-by-side)β
Comparison table. The main table above is BST only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 10K add randomly | 5.50 | - | - | - |
| 10K add & delete randomly | 10.01 | - | - | - |
| 10K addMany | 11.62 | - | - | - |
| 10K get | 10.65 | - | - | - |
BinaryTreeβ
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 1K add randomly | 9.77 | 9.52 | 10.28 | Β±0.36% |
| 1K add & delete randomly | 10.05 | 9.67 | 11.34 | Β±0.69% |
| 1K addMany | 10.79 | 9.20 | 84.26 | Β±19.64% |
| 1K get | 9.64 | 9.15 | 12.52 | Β±1.33% |
| 1K has | 9.50 | 9.20 | 11.91 | Β±0.76% |
| 1K dfs | 92.87 | 90.46 | 96.24 | Β±0.62% |
| 1K bfs | 37.34 | 36.18 | 42.30 | Β±0.7% |
| 1K morris | 37.49 | 36.29 | 39.54 | Β±0.51% |
BinaryTree (side-by-side)β
Comparison table. The main table above is BinaryTree only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 1K add randomly | 9.77 | - | - | - |
| 1K add & delete randomly | 10.05 | - | - | - |
| 1K addMany | 10.79 | - | - | - |
| 1K get | 9.64 | - | - | - |
| 1K has | 9.50 | - | - | - |
| 1K dfs | 92.87 | - | - | - |
| 1K bfs | 37.34 | - | - | - |
| 1K morris | 37.49 | - | - | - |
HashMapβ
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 1M set | 146.17 | 84.97 | 644.99 | Β±33.94% |
| 1M set & get | 141.88 | 106.42 | 178.02 | Β±6.1% |
| 1M ObjKey set & get | 223.16 | 210.45 | 300.73 | Β±5.48% |
HashMap (side-by-side)β
Comparison table. The main table above is HashMap only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 1M set | 146.17 | 144.83 | 76.26 | 94.16 |
| 1M set & get | 141.88 | 200.47 | 75.25 | 67.16 |
| 1M ObjKey set & get | 223.16 | 206.62 | 84.40 | 382.79 |
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 100K add | 141.10 | 78.57 | 1348.32 | Β±65.27% |
| 100K getWords | 57.16 | 52.58 | 63.12 | Β±1.37% |
Trie (side-by-side)β
Comparison table. The main table above is Trie only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 100K add | 141.10 | - | - | - |
| 100K getWords | 57.16 | - | - | - |
DirectedGraphβ
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 1K addVertex | 0.05 | 0.05 | 0.05 | Β±0.43% |
| 1K addEdge | 0.00 | - | - | Β±0% |
| 1K getVertex | 37.54 | 36.05 | 38.86 | Β±0.39% |
| 1K getEdge | 74.48 | 72.60 | 77.63 | Β±0.44% |
| tarjan | 0.38 | 0.34 | 0.42 | Β±0.93% |
| topologicalSort | 0.24 | 0.23 | 0.26 | Β±0.51% |
DirectedGraph (side-by-side)β
Comparison table. The main table above is DirectedGraph only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 1K addVertex | 0.05 | - | - | - |
| 1K addEdge | 0.00 | - | - | - |
| 1K getVertex | 37.54 | - | - | - |
| 1K getEdge | 74.48 | - | - | - |
| tarjan | 0.38 | - | - | - |
| topologicalSort | 0.24 | - | - | - |
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 1M push | 46.38 | 31.28 | 258.38 | Β±26.06% |
| 1M push & pop | 34.59 | 27.52 | 121.56 | Β±14.83% |
Stack (side-by-side)β
Comparison table. The main table above is Stack only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 1M push | 46.38 | 30.28 | 1.65 | 32.38 |
| 1M push & pop | 34.59 | 34.53 | 2.62 | 34.45 |
red-black-tree-cjsβ
| Test Case | Avg (ms) | Min (ms) | Max (ms) | Stability |
|---|
| 1M get | 97.57 | 75.66 | 115.14 | Β±22.94% |
| 1M upd SEQ | 85.76 | 78.96 | 92.92 | Β±8.16% |
| 1M upd RAND | 113.48 | 101.84 | 120.90 | Β±7.77% |
| 1M ins SEQ | 493.45 | 436.86 | 670.44 | Β±25.42% |
| 1M ins RAND | 1023.19 | 976.56 | 1094.17 | Β±5.36% |
| 1M keys-only | 4.22 | 2.71 | 5.90 | Β±41.83% |
red-black-tree-cjs (side-by-side)β
Comparison table. The main table above is red-black-tree-cjs only.
Native is - when there is no apples-to-apples equivalent in this benchmark.
| Test Case | DST (ms) | Native (ms) | C++ (ms) | js-sdsl (ms) |
|---|
| 1M get | 97.57 | - | - | - |
| 1M upd SEQ | 85.76 | - | - | - |
| 1M upd RAND | 113.48 | - | - | - |
| 1M ins SEQ | 493.45 | - | - | - |
| 1M ins RAND | 1023.19 | - | - | - |
| 1M keys-only | 4.22 | - | - | - |
Real-World Scenariosβ
Scenario 1: Message Queue Processingβ
Problem: Process 100,000 messages in a queue.
const queue = [];
for (let msg of incomingMessages) queue.push(msg);
for (let i = 0; i < 100000; i++) {
const msg = queue.shift();
processMessage(msg);
}
import { Deque } from 'data-structure-typed';
const deque = new Deque();
for (let msg of incomingMessages) deque.push(msg);
for (let i = 0; i < 100000; i++) {
const msg = deque.shift();
processMessage(msg);
}
Real Impact: In a system handling 10,000 requests/second, this saves 475ms per second of latency.
Scenario 2: Leaderboard Rankingβ
Problem: Maintain top 100 players with constantly changing scores.
const players = [];
function updateScore(playerId, newScore) {
const idx = players.findIndex(p => p.id === playerId);
players[idx].score = newScore;
players.sort((a, b) => b.score - a.score);
}
import { RedBlackTree } from 'data-structure-typed';
const leaderboard = new RedBlackTree<number, number>();
function updateScore(playerId, newScore) {
leaderboard.set(playerId, newScore);
}
Real Impact: Live leaderboards update instantly instead of lagging.
Scenario 3: Task Scheduling by Priorityβ
Problem: Execute tasks in priority order with 10K pending tasks.
const tasks = [];
function addTask(task) {
tasks.push(task);
tasks.sort((a, b) => b.priority - a.priority);
}
function nextTask() {
return tasks.shift();
}
import { MaxPriorityQueue } from 'data-structure-typed';
const pq = new MaxPriorityQueue();
function addTask(task) {
pq.add(task);
}
function nextTask() {
return pq.poll();
}
Detailed Benchmarksβ
| Operation | Array | Deque | Speed-up |
|---|
| 100K shifts | 2829ms | 5.83ms | 485x |
| 100K unshifts | 2847ms | 6.12ms | 465x |
| 100K operations | 2900ms | 7.45ms | 390x |
| Data Size | Array.sort | RedBlackTree | Speed-up |
|---|
| 1K items | 0.8ms | 3.2ms* | 0.25x (sort faster) |
| 10K items | 12ms | 18ms** | ~0.66x |
| 100K items | 150ms | 165ms** | ~0.9x |
| 1M items | 1800ms | 1950ms** | ~0.92x |
*First time - not repeated sorts
**Maintains sorted order throughout
Key Insight: For repeated operations (updates with resorts), RBTree is much faster:
| Scenario | Array | RBTree | Speed-up |
|---|
| Insert 1K, sort once | 2ms | 5ms | 0.4x |
| Insert 1K, resort 100x | 200ms | 5ms | 40x |
| Insert 100K, resort 1000x | 20000ms | 65ms | 308x |
| Structure | 1K items | 10K items | 100K items |
|---|
| Array (linear) | 0.5ms | 5ms | 50ms |
| BST (balanced) | 0.01ms | 0.013ms | 0.015ms |
| RedBlackTree | 0.01ms | 0.013ms | 0.015ms |
| HashMap | 0.001ms | 0.001ms | 0.001ms |
Memory Usageβ
| Data Structure | 1K items | 10K items | 100K items | 1M items |
|---|
| Array | 39 KB | 242 KB | 2,706 KB | 21,519 KB |
| Queue | 38 KB | 248 KB | 2,712 KB | 21,527 KB |
| Deque | 53 KB | 147 KB | 1,341 KB | 10,717 KB |
| SinglyLinkedList | 60 KB | 425 KB | 3,947 KB | 39,100 KB |
| DoublyLinkedList | 60 KB | 502 KB | 4,726 KB | 46,909 KB |
| Stack | 42 KB | 240 KB | 2,709 KB | 21,521 KB |
| Heap | 35 KB | 250 KB | 2,716 KB | 21,530 KB |
| PriorityQueue | 39 KB | 245 KB | 2,711 KB | 21,524 KB |
| Trie | 526 KB | 3,040 KB | 29,160 KB | 270,733 KB |
| RedBlackTree | 570 KB | 1,069 KB | 8,765 KB | 86,035 KB |
| TreeCounter | 553 KB | 1,134 KB | 11,099 KB | 91,415 KB |
| TreeMultiMap | 2,069 KB | 4,836 KB | 32,828 KB | 208,619 KB |
C++ vs JavaScript Data Structure Memory Usage Comparison (1M Elements)β
| Data Structure | C++ | JavaScript | Multiple | Evaluation |
|---|
| Array | 4β8 MB | 21.01 MB | 2.75Γβ5.51Γ | JavaScript uses significantly more memory due to object model and GC overhead |
| Queue | 8β24 MB | 21.02 MB | 0.92Γβ2.76Γ | Memory usage depends heavily on the C++ implementation strategy |
| Deque | 8β24 MB | 10.47 MB | 0.46Γβ1.37Γ | JavaScript implementation is relatively memory-efficient in this case |
| SinglyLinkedList | 24β40 MB | 38.18 MB | 1.00Γβ1.67Γ | Similar memory footprint; both suffer from per-node allocation overhead |
| DoublyLinkedList | 32β56 MB | 45.81 MB | 0.86Γβ1.50Γ | Comparable memory usage; allocator overhead dominates in both languages |
| Stack | 4β8 MB | 21.02 MB | 2.75Γβ5.51Γ | JavaScript stacks are much heavier than C++ vector-based stacks |
| Heap | 4β8 MB | 21.03 MB | 2.76Γβ5.51Γ | JavaScript heap implementations incur substantial runtime overhead |
| PriorityQueue | 4β8 MB | 21.02 MB | 2.76Γβ5.51Γ | Similar to Heap; JavaScript pays extra metadata and GC costs |
| Trie | 32β160 MB | 264.39 MB | 1.73Γβ8.66Γ | Highly implementation-dependent; JavaScript object-based tries are very memory-intensive |
| RedBlackTree | 48β80 MB | 84.02 MB | 1.10Γβ1.84Γ | JavaScript trees are larger, but the gap is moderate compared to arrays |
| TreeCounter | 56β88 MB | 89.27 MB | 1.06Γβ1.67Γ | Additional per-node bookkeeping increases JavaScript memory usage |
| TreeMultiMap | 56β96 MB | 203.73 MB | 2.23Γβ3.81Γ | Deep object nesting significantly amplifies memory consumption in JavaScript |
When to Use Whatβ
Decision Matrixβ
| Need... | Use... | Complexity | Notes |
|---|
| Random access by index | Array | O(1) access | Standard choice |
| Sorted order with updates | RedBlackTree | O(log n) all ops | Auto-maintained |
| Priority queue | PriorityQueue | O(log n) add/remove | Keeps order |
| Fast head/tail ops | Deque | O(1) all ops | Best for queues |
| Prefix search | Trie | O(m+k) | m=prefix length |
| Undo/redo stack | Stack | O(1) all ops | LIFO order |
| Message queue | Queue/Deque | O(1) all ops | FIFO order |
| Graph algorithms | DirectedGraph | Varies | DFS, BFS, Dijkstra |
| Key-value lookup | Map | O(1) avg | When unsorted OK |
| Just sorting once | Array.sort() | O(n log n) | One-time cost OK |
Quick Decision Guideβ
Need frequent head/tail operations?
YES β Deque (O(1) shift/unshift/push/pop)
NO β Next
Need sorted + fast lookup?
YES β RedBlackTree (O(log n) guaranteed)
NO β Next
Need highest/lowest priority?
YES β Heap/PriorityQueue (O(log n) add/remove)
NO β Next
Need prefix/text matching?
YES β Trie (O(m+k) where m=prefix)
NO β Next
Need graph operations?
YES β DirectedGraph/UndirectedGraph
NO β Use Array (simplest case)
Optimization Tipsβ
Tip 1: Batch Operationsβ
const tree = new RedBlackTree();
for (const item of items) {
tree.set(item.id, item);
}
const tree = new RedBlackTree(items);
Tip 2: Use Right Structure Earlyβ
const data = [];
for (const item of input) data.push(item);
const sorted = [...new RedBlackTree(data).keys()];
const tree = new RedBlackTree(input);
const sorted = [...tree.keys()];
Tip 3: Chain Operationsβ
const tree = new RedBlackTree(data);
const result = tree.toArray()
.filter(x => x > 5)
.map(x => x * 2);
const result = tree
.filter((v => (v ?? 0) > 5)
.map(((v, k) => [k, (x ?? 0) * 2]);
Tip 4: V8 JIT Warm-upβ
const tree = new RedBlackTree();
for (let i = 0; i < 1000; i++) tree.set(i, i);
Tip 5: Choose Right Comparatorβ
const tree = new RedBlackTree((a, b) => {
if (a.category !== b.category) {
return a.category.localeCompare(b.category);
}
return a.priority - b.priority;
});
const tree = new RedBlackTree([], { comparator: (a, b) => a - b)
}
;
Benchmark Summary Tableβ
Operations per Secondβ
| Operation | Array | Deque | Tree | Heap |
|---|
| 1K shifts | 353/sec | 171K/sec | - | - |
| 1K inserts | 625/sec | 625/sec | 10K/sec | 8K/sec |
| 1K searches | 2K/sec | - | 100K/sec | 1K/sec |
| 1K sorts | 1/sec | - | 1000/sec* | - |
*Maintains sorted order
Conclusionβ
When to Optimizeβ
- Profile first: Don't optimize without data
- Hot paths only: Focus on frequently-called code
- Right structure matters: large speedups are possible (see the measured scenarios above)
- Small datasets: Array usually fine
- Large datasets: Structure choice critical
Array.sort() β Simple, once per session
RedBlackTree β Sorted + frequent updates
Deque β Frequent head/tail ops
Heap β Priority matters
Trie β Prefix search
HashMap/Map β Unsorted key-value lookup
Need examples? See GUIDES.md.
Understand why? Read ARCHITECTURE.md.