@calcit/ternary-tree 0.0.23 → 0.0.25
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/README.md +24 -4
- package/TESTING.md +155 -0
- package/lib/benchmark.d.mts +1 -0
- package/lib/benchmark.mjs +67 -0
- package/lib/list.d.mts +2 -0
- package/lib/list.mjs +178 -124
- package/lib/map.mjs +124 -101
- package/lib/test-list-detailed-perf.d.mts +1 -0
- package/lib/test-list-detailed-perf.mjs +165 -0
- package/lib/test-list-perf.d.mts +1 -0
- package/lib/test-list-perf.mjs +153 -0
- package/lib/test-list.mjs +202 -203
- package/lib/test-map-perf.d.mts +1 -0
- package/lib/test-map-perf.mjs +70 -0
- package/lib/test-map.mjs +201 -208
- package/lib/test-utils.d.mts +9 -5
- package/lib/test-utils.mjs +131 -18
- package/lib/{main.mjs → test.mjs} +5 -0
- package/package.json +13 -5
- /package/lib/{main.d.mts → test.d.mts} +0 -0
package/lib/map.mjs
CHANGED
@@ -159,24 +159,21 @@ export function initTernaryTreeMap(t) {
|
|
159
159
|
}
|
160
160
|
// use for..in for performance
|
161
161
|
export function initTernaryTreeMapFromArray(t) {
|
162
|
-
|
162
|
+
// Use Map instead of Record for better performance with numeric keys
|
163
|
+
let groupBuffers = new Map();
|
163
164
|
let xs = [];
|
164
|
-
|
165
|
+
const length = t.length;
|
166
|
+
for (let idx = 0; idx < length; idx++) {
|
165
167
|
let k = t[idx][0];
|
166
168
|
let v = t[idx][1];
|
167
169
|
let h = hashGenerator(k);
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
branch.push([k, v]);
|
172
|
-
}
|
173
|
-
else {
|
174
|
-
throw new Error("Expected referece to pairs");
|
175
|
-
}
|
170
|
+
let branch = groupBuffers.get(h);
|
171
|
+
if (branch != null) {
|
172
|
+
branch.push([k, v]);
|
176
173
|
}
|
177
174
|
else {
|
178
175
|
let pairs = [[k, v]];
|
179
|
-
groupBuffers
|
176
|
+
groupBuffers.set(h, pairs);
|
180
177
|
xs.push({
|
181
178
|
hash: h,
|
182
179
|
pairs: pairs,
|
@@ -285,11 +282,15 @@ function collectHashSortedArray(tree, acc, idx) {
|
|
285
282
|
else {
|
286
283
|
switch (tree.kind) {
|
287
284
|
case TernaryTreeKind.ternaryTreeLeaf: {
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
285
|
+
// Cache elements and current index to reduce property access
|
286
|
+
const elements = tree.elements;
|
287
|
+
const length = elements.length;
|
288
|
+
let currentIdx = idx.value;
|
289
|
+
for (let i = 0; i < length; i++) {
|
290
|
+
acc[currentIdx] = elements[i];
|
291
|
+
currentIdx++;
|
292
292
|
}
|
293
|
+
idx.value = currentIdx;
|
293
294
|
break;
|
294
295
|
}
|
295
296
|
case TernaryTreeKind.ternaryTreeBranch: {
|
@@ -317,8 +318,10 @@ function collectOrderedHashEntries(tree, acc, idx) {
|
|
317
318
|
else {
|
318
319
|
switch (tree.kind) {
|
319
320
|
case TernaryTreeKind.ternaryTreeLeaf: {
|
320
|
-
|
321
|
-
|
321
|
+
// Cache current index to reduce property access
|
322
|
+
const currentIdx = idx.value;
|
323
|
+
acc[currentIdx] = { hash: tree.hash, pairs: tree.elements };
|
324
|
+
idx.value = currentIdx + 1;
|
322
325
|
break;
|
323
326
|
}
|
324
327
|
case TernaryTreeKind.ternaryTreeBranch: {
|
@@ -344,85 +347,88 @@ export function contains(originalTree, item) {
|
|
344
347
|
if (originalTree == null) {
|
345
348
|
return false;
|
346
349
|
}
|
347
|
-
// TODO
|
348
350
|
// reduce redundant computation by reusing hash result
|
349
351
|
let hx = hashGenerator(item);
|
350
352
|
let tree = originalTree;
|
351
353
|
whileLoop: while (tree != null) {
|
352
354
|
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
353
355
|
if (hx === tree.hash) {
|
354
|
-
|
356
|
+
// Cache elements length to avoid repeated property access
|
357
|
+
const elements = tree.elements;
|
358
|
+
const size = elements.length;
|
355
359
|
for (let idx = 0; idx < size; idx++) {
|
356
|
-
|
357
|
-
if (dataEqual(pair[0], item)) {
|
360
|
+
if (dataEqual(elements[idx][0], item)) {
|
358
361
|
return true;
|
359
362
|
}
|
360
363
|
}
|
361
364
|
}
|
362
365
|
return false;
|
363
366
|
}
|
364
|
-
//
|
365
|
-
|
367
|
+
// Optimize branch navigation with early exits
|
368
|
+
const left = tree.left;
|
369
|
+
if (left == null) {
|
366
370
|
return false;
|
367
371
|
}
|
368
|
-
if (
|
369
|
-
if (hx <
|
372
|
+
if (left.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
373
|
+
if (hx < left.hash) {
|
370
374
|
return false;
|
371
375
|
}
|
372
|
-
if (
|
373
|
-
tree =
|
374
|
-
continue whileLoop;
|
376
|
+
if (left.hash === hx) {
|
377
|
+
tree = left;
|
378
|
+
continue whileLoop;
|
375
379
|
}
|
376
380
|
}
|
377
381
|
else {
|
378
|
-
if (hx <
|
382
|
+
if (hx < left.minHash) {
|
379
383
|
return false;
|
380
384
|
}
|
381
|
-
if (hx <=
|
382
|
-
tree =
|
383
|
-
continue whileLoop;
|
385
|
+
if (hx <= left.maxHash) {
|
386
|
+
tree = left;
|
387
|
+
continue whileLoop;
|
384
388
|
}
|
385
389
|
}
|
386
|
-
|
390
|
+
const middle = tree.middle;
|
391
|
+
if (middle == null) {
|
387
392
|
return false;
|
388
393
|
}
|
389
|
-
if (
|
390
|
-
if (hx <
|
394
|
+
if (middle.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
395
|
+
if (hx < middle.hash) {
|
391
396
|
return false;
|
392
397
|
}
|
393
|
-
if (
|
394
|
-
tree =
|
395
|
-
continue whileLoop;
|
398
|
+
if (middle.hash === hx) {
|
399
|
+
tree = middle;
|
400
|
+
continue whileLoop;
|
396
401
|
}
|
397
402
|
}
|
398
403
|
else {
|
399
|
-
if (hx <
|
404
|
+
if (hx < middle.minHash) {
|
400
405
|
return false;
|
401
406
|
}
|
402
|
-
if (hx <=
|
403
|
-
tree =
|
404
|
-
continue whileLoop;
|
407
|
+
if (hx <= middle.maxHash) {
|
408
|
+
tree = middle;
|
409
|
+
continue whileLoop;
|
405
410
|
}
|
406
411
|
}
|
407
|
-
|
412
|
+
const right = tree.right;
|
413
|
+
if (right == null) {
|
408
414
|
return false;
|
409
415
|
}
|
410
|
-
if (
|
411
|
-
if (hx <
|
416
|
+
if (right.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
417
|
+
if (hx < right.hash) {
|
412
418
|
return false;
|
413
419
|
}
|
414
|
-
if (
|
415
|
-
tree =
|
416
|
-
continue whileLoop;
|
420
|
+
if (right.hash === hx) {
|
421
|
+
tree = right;
|
422
|
+
continue whileLoop;
|
417
423
|
}
|
418
424
|
}
|
419
425
|
else {
|
420
|
-
if (hx <
|
426
|
+
if (hx < right.minHash) {
|
421
427
|
return false;
|
422
428
|
}
|
423
|
-
if (hx <=
|
424
|
-
tree =
|
425
|
-
continue whileLoop;
|
429
|
+
if (hx <= right.maxHash) {
|
430
|
+
tree = right;
|
431
|
+
continue whileLoop;
|
426
432
|
}
|
427
433
|
}
|
428
434
|
return false;
|
@@ -434,77 +440,81 @@ export function mapGetDefault(originalTree, item, v0) {
|
|
434
440
|
let tree = originalTree;
|
435
441
|
whileLoop: while (tree != null) {
|
436
442
|
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
437
|
-
|
443
|
+
// Cache elements array to avoid repeated property access
|
444
|
+
const elements = tree.elements;
|
445
|
+
const size = elements.length;
|
438
446
|
for (let i = 0; i < size; i++) {
|
439
|
-
|
440
|
-
|
441
|
-
return pair[1];
|
447
|
+
if (dataEqual(elements[i][0], item)) {
|
448
|
+
return elements[i][1];
|
442
449
|
}
|
443
450
|
}
|
444
451
|
return v0;
|
445
452
|
}
|
446
|
-
//
|
447
|
-
|
453
|
+
// Cache tree children to avoid repeated property access
|
454
|
+
const left = tree.left;
|
455
|
+
if (left == null) {
|
448
456
|
return v0;
|
449
457
|
}
|
450
|
-
if (
|
451
|
-
if (hx <
|
458
|
+
if (left.kind == TernaryTreeKind.ternaryTreeLeaf) {
|
459
|
+
if (hx < left.hash) {
|
452
460
|
return v0;
|
453
461
|
}
|
454
|
-
if (
|
455
|
-
tree =
|
456
|
-
continue whileLoop;
|
462
|
+
if (left.hash === hx) {
|
463
|
+
tree = left;
|
464
|
+
continue whileLoop;
|
457
465
|
}
|
458
466
|
}
|
459
467
|
else {
|
460
|
-
if (hx <
|
468
|
+
if (hx < left.minHash) {
|
461
469
|
return v0;
|
462
470
|
}
|
463
|
-
if (hx <=
|
464
|
-
tree =
|
465
|
-
continue whileLoop;
|
471
|
+
if (hx <= left.maxHash) {
|
472
|
+
tree = left;
|
473
|
+
continue whileLoop;
|
466
474
|
}
|
467
475
|
}
|
468
|
-
|
476
|
+
const middle = tree.middle;
|
477
|
+
if (middle == null) {
|
469
478
|
return v0;
|
470
479
|
}
|
471
|
-
if (
|
472
|
-
if (hx <
|
480
|
+
if (middle.kind == TernaryTreeKind.ternaryTreeLeaf) {
|
481
|
+
if (hx < middle.hash) {
|
473
482
|
return v0;
|
474
483
|
}
|
475
|
-
if (
|
476
|
-
tree =
|
477
|
-
continue whileLoop;
|
484
|
+
if (middle.hash === hx) {
|
485
|
+
tree = middle;
|
486
|
+
continue whileLoop;
|
478
487
|
}
|
479
488
|
}
|
480
489
|
else {
|
481
|
-
if (hx <
|
490
|
+
if (hx < middle.minHash) {
|
482
491
|
return v0;
|
483
492
|
}
|
484
|
-
if (hx <=
|
485
|
-
tree =
|
486
|
-
continue whileLoop;
|
493
|
+
if (hx <= middle.maxHash) {
|
494
|
+
tree = middle;
|
495
|
+
continue whileLoop;
|
487
496
|
}
|
488
497
|
}
|
489
|
-
|
498
|
+
const right = tree.right;
|
499
|
+
if (right == null) {
|
490
500
|
return v0;
|
491
501
|
}
|
492
|
-
if (
|
493
|
-
if (hx <
|
502
|
+
if (right.kind == TernaryTreeKind.ternaryTreeLeaf) {
|
503
|
+
if (hx < right.hash) {
|
494
504
|
return v0;
|
495
505
|
}
|
496
|
-
if (
|
497
|
-
tree =
|
498
|
-
continue whileLoop;
|
506
|
+
if (right.hash === hx) {
|
507
|
+
tree = right;
|
508
|
+
continue whileLoop;
|
499
509
|
}
|
500
510
|
}
|
501
511
|
else {
|
502
|
-
if (hx <
|
512
|
+
if (hx < right.minHash) {
|
503
513
|
return v0;
|
504
514
|
}
|
505
|
-
if (hx <=
|
506
|
-
tree =
|
507
|
-
continue whileLoop;
|
515
|
+
if (hx <= right.maxHash) {
|
516
|
+
tree = right;
|
517
|
+
continue whileLoop;
|
508
518
|
}
|
509
519
|
}
|
510
520
|
return v0;
|
@@ -1025,28 +1035,38 @@ export function dissocMap(tree, key) {
|
|
1025
1035
|
function collectToPairsArray(acc, tree) {
|
1026
1036
|
if (tree != null) {
|
1027
1037
|
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1038
|
+
// Cache elements array and use batch push for better performance
|
1039
|
+
const elements = tree.elements;
|
1040
|
+
const length = elements.length;
|
1041
|
+
for (let i = 0; i < length; i++) {
|
1042
|
+
acc.push(elements[i]);
|
1031
1043
|
}
|
1032
1044
|
}
|
1033
1045
|
else {
|
1034
|
-
|
1035
|
-
|
1046
|
+
// Cache children to avoid repeated property access
|
1047
|
+
const left = tree.left;
|
1048
|
+
const middle = tree.middle;
|
1049
|
+
const right = tree.right;
|
1050
|
+
if (left != null) {
|
1051
|
+
collectToPairsArray(acc, left);
|
1036
1052
|
}
|
1037
|
-
if (
|
1038
|
-
collectToPairsArray(acc,
|
1053
|
+
if (middle != null) {
|
1054
|
+
collectToPairsArray(acc, middle);
|
1039
1055
|
}
|
1040
|
-
if (
|
1041
|
-
collectToPairsArray(acc,
|
1056
|
+
if (right != null) {
|
1057
|
+
collectToPairsArray(acc, right);
|
1042
1058
|
}
|
1043
1059
|
}
|
1044
1060
|
}
|
1045
1061
|
}
|
1046
1062
|
/** similar to `toPairs`, but using Array.push directly */
|
1047
1063
|
export function toPairsArray(tree) {
|
1048
|
-
|
1049
|
-
|
1064
|
+
// Pre-allocate array with known size for better performance
|
1065
|
+
const totalSize = mapLen(tree);
|
1066
|
+
let result = new Array(totalSize);
|
1067
|
+
let idx = { value: 0 };
|
1068
|
+
// Use the more efficient collectHashSortedArray instead
|
1069
|
+
collectHashSortedArray(tree, result, idx);
|
1050
1070
|
return result;
|
1051
1071
|
}
|
1052
1072
|
export function* toPairs(tree) {
|
@@ -1254,10 +1274,13 @@ export function mapMapValues(tree, f) {
|
|
1254
1274
|
}
|
1255
1275
|
switch (tree.kind) {
|
1256
1276
|
case TernaryTreeKind.ternaryTreeLeaf: {
|
1257
|
-
|
1258
|
-
|
1277
|
+
// Cache elements array and pre-allocate result
|
1278
|
+
const elements = tree.elements;
|
1279
|
+
const size = elements.length;
|
1280
|
+
let newElements = new Array(size);
|
1259
1281
|
for (let idx = 0; idx < size; idx++) {
|
1260
|
-
|
1282
|
+
const element = elements[idx];
|
1283
|
+
newElements[idx] = [element[0], f(element[1])];
|
1261
1284
|
}
|
1262
1285
|
let result = {
|
1263
1286
|
kind: TernaryTreeKind.ternaryTreeLeaf,
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function runDetailedListPerformanceTests(): void;
|
@@ -0,0 +1,165 @@
|
|
1
|
+
import { initTernaryTreeList, initTernaryTreeListFromRange, listGet, assocList, insert, listLen, indexOf, listToItems, prepend, concat, slice, } from "./list.mjs";
|
2
|
+
function createTestListData(size) {
|
3
|
+
const data = [];
|
4
|
+
for (let i = 0; i < size; i++) {
|
5
|
+
data.push(i);
|
6
|
+
}
|
7
|
+
return data;
|
8
|
+
}
|
9
|
+
function measureTime(name, fn) {
|
10
|
+
const start = performance.now();
|
11
|
+
const result = fn();
|
12
|
+
const end = performance.now();
|
13
|
+
const duration = end - start;
|
14
|
+
console.log(`${name}: ${duration.toFixed(2)}ms`);
|
15
|
+
return [result, duration];
|
16
|
+
}
|
17
|
+
function repeatTest(times, fn) {
|
18
|
+
let totalTime = 0;
|
19
|
+
for (let i = 0; i < times; i++) {
|
20
|
+
const start = performance.now();
|
21
|
+
fn();
|
22
|
+
const end = performance.now();
|
23
|
+
totalTime += end - start;
|
24
|
+
}
|
25
|
+
return totalTime / times;
|
26
|
+
}
|
27
|
+
export function runDetailedListPerformanceTests() {
|
28
|
+
console.log("\n=== Detailed List Performance Tests ===");
|
29
|
+
console.log("Testing various operations with different list sizes to show optimization benefits\n");
|
30
|
+
const sizes = [500, 2000, 8000, 16000];
|
31
|
+
for (const size of sizes) {
|
32
|
+
console.log(`\n--- Performance Analysis: ${size} elements ---`);
|
33
|
+
const testData = createTestListData(size);
|
34
|
+
// Test list creation - should benefit from reduced overhead
|
35
|
+
const [treeList, creationTime] = measureTime(`Create list (${size})`, () => {
|
36
|
+
return initTernaryTreeList(testData);
|
37
|
+
});
|
38
|
+
// Test range creation
|
39
|
+
measureTime(`Range init (${size})`, () => {
|
40
|
+
return initTernaryTreeListFromRange(testData, 0, size);
|
41
|
+
});
|
42
|
+
// Test random access patterns - benefits from cached size calculations
|
43
|
+
const accessCount = Math.min(1000, size);
|
44
|
+
const indices = Array.from({ length: accessCount }, () => Math.floor(Math.random() * size));
|
45
|
+
const avgAccessTime = repeatTest(3, () => {
|
46
|
+
for (const idx of indices) {
|
47
|
+
listGet(treeList, idx);
|
48
|
+
}
|
49
|
+
});
|
50
|
+
console.log(`Random access avg (${accessCount} ops): ${avgAccessTime.toFixed(2)}ms`);
|
51
|
+
// Test sequential access
|
52
|
+
const avgSeqTime = repeatTest(3, () => {
|
53
|
+
for (let i = 0; i < Math.min(size, 1000); i++) {
|
54
|
+
listGet(treeList, i);
|
55
|
+
}
|
56
|
+
});
|
57
|
+
console.log(`Sequential access avg (${Math.min(size, 1000)} ops): ${avgSeqTime.toFixed(2)}ms`);
|
58
|
+
// Test structural modifications - heavily benefits from cached calculations
|
59
|
+
const modCount = Math.min(100, size / 10);
|
60
|
+
const avgAssocTime = repeatTest(3, () => {
|
61
|
+
let list = treeList;
|
62
|
+
for (let i = 0; i < modCount; i++) {
|
63
|
+
const idx = Math.floor(Math.random() * size);
|
64
|
+
list = assocList(list, idx, idx * 2);
|
65
|
+
}
|
66
|
+
return list;
|
67
|
+
});
|
68
|
+
console.log(`Assoc operations avg (${modCount} ops): ${avgAssocTime.toFixed(2)}ms`);
|
69
|
+
// Test insertions
|
70
|
+
const insertCount = Math.min(50, size / 20);
|
71
|
+
const avgInsertTime = repeatTest(3, () => {
|
72
|
+
let list = treeList;
|
73
|
+
for (let i = 0; i < insertCount; i++) {
|
74
|
+
const idx = Math.min(Math.floor(Math.random() * (size + i)), listLen(list));
|
75
|
+
list = insert(list, idx, i + size);
|
76
|
+
}
|
77
|
+
return list;
|
78
|
+
});
|
79
|
+
console.log(`Insert operations avg (${insertCount} ops): ${avgInsertTime.toFixed(2)}ms`);
|
80
|
+
// Test search operations - benefits from cached property access
|
81
|
+
const searchCount = Math.min(100, size / 10);
|
82
|
+
const searchValues = testData.slice(0, searchCount);
|
83
|
+
const avgSearchTime = repeatTest(3, () => {
|
84
|
+
for (const value of searchValues) {
|
85
|
+
indexOf(treeList, value);
|
86
|
+
}
|
87
|
+
});
|
88
|
+
console.log(`Search operations avg (${searchCount} ops): ${avgSearchTime.toFixed(2)}ms`);
|
89
|
+
// Test slicing - benefits from cached size calculations
|
90
|
+
const sliceCount = Math.min(20, size / 50);
|
91
|
+
const avgSliceTime = repeatTest(3, () => {
|
92
|
+
for (let i = 0; i < sliceCount; i++) {
|
93
|
+
const start = Math.floor((Math.random() * size) / 2);
|
94
|
+
const end = start + Math.floor((Math.random() * size) / 4);
|
95
|
+
slice(treeList, start, Math.min(end, size));
|
96
|
+
}
|
97
|
+
});
|
98
|
+
console.log(`Slice operations avg (${sliceCount} ops): ${avgSliceTime.toFixed(2)}ms`);
|
99
|
+
// Iteration performance
|
100
|
+
const avgIterTime = repeatTest(3, () => {
|
101
|
+
let count = 0;
|
102
|
+
for (const item of listToItems(treeList)) {
|
103
|
+
count++;
|
104
|
+
}
|
105
|
+
return count;
|
106
|
+
});
|
107
|
+
console.log(`Iterator traversal avg (${size} items): ${avgIterTime.toFixed(2)}ms`);
|
108
|
+
// Complex operation chains - should show cumulative benefits
|
109
|
+
measureTime(`Complex chain (${Math.floor(size / 100)} ops)`, () => {
|
110
|
+
let list = treeList;
|
111
|
+
const ops = Math.floor(size / 100);
|
112
|
+
for (let i = 0; i < ops; i++) {
|
113
|
+
// Prepend
|
114
|
+
list = prepend(list, -i);
|
115
|
+
// Random assoc
|
116
|
+
if (listLen(list) > 10) {
|
117
|
+
const idx = Math.floor(Math.random() * Math.min(listLen(list), 100));
|
118
|
+
list = assocList(list, idx, i * 1000);
|
119
|
+
}
|
120
|
+
// Random access
|
121
|
+
if (listLen(list) > 5) {
|
122
|
+
listGet(list, Math.floor(Math.random() * Math.min(listLen(list), 50)));
|
123
|
+
}
|
124
|
+
}
|
125
|
+
return list;
|
126
|
+
});
|
127
|
+
console.log("");
|
128
|
+
}
|
129
|
+
// Stress test for deep operations
|
130
|
+
console.log("=== Stress Tests ===");
|
131
|
+
const largeList = initTernaryTreeList(createTestListData(50000));
|
132
|
+
measureTime("Deep list access stress", () => {
|
133
|
+
const samples = 1000;
|
134
|
+
for (let i = 0; i < samples; i++) {
|
135
|
+
const idx = Math.floor(Math.random() * 50000);
|
136
|
+
listGet(largeList, idx);
|
137
|
+
}
|
138
|
+
});
|
139
|
+
measureTime("Deep list modification stress", () => {
|
140
|
+
let list = largeList;
|
141
|
+
for (let i = 0; i < 100; i++) {
|
142
|
+
const idx = Math.floor(Math.random() * listLen(list));
|
143
|
+
list = assocList(list, idx, i * 10000);
|
144
|
+
}
|
145
|
+
return list;
|
146
|
+
});
|
147
|
+
// Memory efficiency test
|
148
|
+
console.log("\n=== Memory Efficiency Tests ===");
|
149
|
+
measureTime("Large tree creation (100k)", () => {
|
150
|
+
return initTernaryTreeList(createTestListData(100000));
|
151
|
+
});
|
152
|
+
// Test concatenation performance
|
153
|
+
console.log("\n=== Concatenation Performance ===");
|
154
|
+
const list1 = initTernaryTreeList(createTestListData(5000));
|
155
|
+
const list2 = initTernaryTreeList(createTestListData(5000));
|
156
|
+
const list3 = initTernaryTreeList(createTestListData(5000));
|
157
|
+
const list4 = initTernaryTreeList(createTestListData(5000));
|
158
|
+
measureTime("Concat 4 large lists (5k each)", () => {
|
159
|
+
return concat(concat(concat(list1, list2), list3), list4);
|
160
|
+
});
|
161
|
+
console.log("\n✅ Performance testing completed!");
|
162
|
+
}
|
163
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
164
|
+
runDetailedListPerformanceTests();
|
165
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function runListPerformanceTests(): void;
|