Skip to content

Commit fc1a4bf

Browse files
authored
Merge pull request #24 from thakugan/master
Add benchmarks and some optimizations for diffAgainst
2 parents fb31d70 + 3f707ea commit fc1a4bf

File tree

3 files changed

+58
-20
lines changed

3 files changed

+58
-20
lines changed

b+tree.js

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -640,14 +640,13 @@ var BTree = /** @class */ (function () {
640640
* @returns true if the step was completed and false if the step would have caused the cursor to move beyond the end of the tree.
641641
*/
642642
BTree.step = function (cursor, stepToNode) {
643-
if (stepToNode === void 0) { stepToNode = false; }
644643
var internalSpine = cursor.internalSpine, levelIndices = cursor.levelIndices, leaf = cursor.leaf;
645-
if (stepToNode || leaf) {
644+
if (stepToNode === true || leaf) {
646645
var levelsLength = levelIndices.length;
647646
// Step to the next node only if:
648647
// - We are explicitly directed to via stepToNode, or
649648
// - There are no key/value pairs left to step to in this leaf
650-
if (stepToNode || levelIndices[levelsLength - 1] === 0) {
649+
if (stepToNode === true || levelIndices[levelsLength - 1] === 0) {
651650
var spineLength = internalSpine.length;
652651
// Root is leaf
653652
if (spineLength === 0)
@@ -656,19 +655,17 @@ var BTree = /** @class */ (function () {
656655
var nodeLevelIndex = spineLength - 1;
657656
var levelIndexWalkBack = nodeLevelIndex;
658657
while (levelIndexWalkBack >= 0) {
659-
var childIndex = levelIndices[levelIndexWalkBack];
660-
if (childIndex > 0) {
658+
if (levelIndices[levelIndexWalkBack] > 0) {
661659
if (levelIndexWalkBack < levelsLength - 1) {
662660
// Remove leaf state from cursor
663661
cursor.leaf = undefined;
664-
levelIndices.splice(levelIndexWalkBack + 1, levelsLength - levelIndexWalkBack);
662+
levelIndices.pop();
665663
}
666-
// If we walked upwards past any internal node, splice them out
664+
// If we walked upwards past any internal node, slice them out
667665
if (levelIndexWalkBack < nodeLevelIndex)
668-
internalSpine.splice(levelIndexWalkBack + 1, spineLength - levelIndexWalkBack);
666+
cursor.internalSpine = internalSpine.slice(0, levelIndexWalkBack + 1);
669667
// Move to new internal node
670-
var nodeIndex = --levelIndices[levelIndexWalkBack];
671-
cursor.currentKey = internalSpine[levelIndexWalkBack][nodeIndex].maxKey();
668+
cursor.currentKey = internalSpine[levelIndexWalkBack][--levelIndices[levelIndexWalkBack]].maxKey();
672669
return true;
673670
}
674671
levelIndexWalkBack--;

b+tree.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -739,14 +739,14 @@ export default class BTree<K=any, V=any> implements ISortedMapF<K,V>, ISortedMap
739739
* @param stepToNode If true, the cursor will be advanced to the next node (skipping values)
740740
* @returns true if the step was completed and false if the step would have caused the cursor to move beyond the end of the tree.
741741
*/
742-
private static step<K, V>(cursor: DiffCursor<K, V>, stepToNode: boolean = false): boolean {
742+
private static step<K, V>(cursor: DiffCursor<K, V>, stepToNode?: boolean): boolean {
743743
const { internalSpine, levelIndices, leaf } = cursor;
744-
if (stepToNode || leaf) {
744+
if (stepToNode === true || leaf) {
745745
const levelsLength = levelIndices.length;
746746
// Step to the next node only if:
747747
// - We are explicitly directed to via stepToNode, or
748748
// - There are no key/value pairs left to step to in this leaf
749-
if (stepToNode || levelIndices[levelsLength - 1] === 0) {
749+
if (stepToNode === true || levelIndices[levelsLength - 1] === 0) {
750750
const spineLength = internalSpine.length;
751751
// Root is leaf
752752
if (spineLength === 0)
@@ -755,19 +755,17 @@ export default class BTree<K=any, V=any> implements ISortedMapF<K,V>, ISortedMap
755755
const nodeLevelIndex = spineLength - 1;
756756
let levelIndexWalkBack = nodeLevelIndex;
757757
while (levelIndexWalkBack >= 0) {
758-
const childIndex = levelIndices[levelIndexWalkBack]
759-
if (childIndex > 0) {
758+
if (levelIndices[levelIndexWalkBack] > 0) {
760759
if (levelIndexWalkBack < levelsLength - 1) {
761760
// Remove leaf state from cursor
762761
cursor.leaf = undefined;
763-
levelIndices.splice(levelIndexWalkBack + 1, levelsLength - levelIndexWalkBack);
762+
levelIndices.pop();
764763
}
765-
// If we walked upwards past any internal node, splice them out
764+
// If we walked upwards past any internal node, slice them out
766765
if (levelIndexWalkBack < nodeLevelIndex)
767-
internalSpine.splice(levelIndexWalkBack + 1, spineLength - levelIndexWalkBack);
766+
cursor.internalSpine = internalSpine.slice(0, levelIndexWalkBack + 1);
768767
// Move to new internal node
769-
const nodeIndex = --levelIndices[levelIndexWalkBack];
770-
cursor.currentKey = internalSpine[levelIndexWalkBack][nodeIndex].maxKey();
768+
cursor.currentKey = internalSpine[levelIndexWalkBack][--levelIndices[levelIndexWalkBack]].maxKey();
771769
return true;
772770
}
773771
levelIndexWalkBack--;

benchmarks.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,4 +310,47 @@ console.log("### Measure effect of max node size ###");
310310
tree.set(keys[i], undefined);
311311
console.log(`${timer.restart()}\tInsert ${tree.size} keys in B+tree with node size ${tree.maxNodeSize}`);
312312
}
313+
}
314+
315+
console.log();
316+
console.log("### Delta between B+ trees");
317+
{
318+
console.log();
319+
const sizes = [100, 1000, 10000, 100000, 1000000];
320+
321+
sizes.forEach((size, i) => {
322+
for (let j = i; j < sizes.length; j++) {
323+
const tree = new BTree();
324+
for (let k of makeArray(size, true))
325+
tree.set(k, k * 10);
326+
327+
const otherSize = sizes[j];
328+
const otherTree = new BTree();
329+
for (let k of makeArray(otherSize, true))
330+
otherTree.set(k, k * 10);
331+
332+
measure(() => `Delta between B+ trees with ${size} nodes and B+tree with ${otherSize} nodes`, () => {
333+
tree.diffAgainst(otherTree);
334+
});
335+
}
336+
})
337+
338+
console.log();
339+
sizes.forEach((size, i) => {
340+
for (let j = 0; j < sizes.length; j++) {
341+
const otherSize = sizes[j];
342+
const keys = makeArray(size + otherSize, true);
343+
const tree = new BTree();
344+
for (let k of keys.slice(0, size))
345+
tree.set(k, k * 10);
346+
347+
const otherTree = tree.clone();
348+
for (let k of keys.slice(size))
349+
tree.set(k, k * 10);
350+
351+
measure(() => `Delta between B+ trees with ${size} nodes and cheap cloned B+tree with ${otherSize} additional nodes`, () => {
352+
tree.diffAgainst(otherTree);
353+
});
354+
}
355+
})
313356
}

0 commit comments

Comments
 (0)