Skip to content
This repository was archived by the owner on Aug 4, 2026. It is now read-only.

Commit 320f354

Browse files
committed
Final implementation of MemoryBTree and MemoryQueue
1 parent 92b8dfa commit 320f354

58 files changed

Lines changed: 5152 additions & 2306 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,3 @@
1717
# frontend code
1818
node_modules/
1919
dist/
20-
21-
# internal
22-
drafts/
23-
tests/drafts/
24-
bench/drafts/

bench/MemoryBTree/BTree-specific-fns.bench.mo

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import Array "mo:base/Array";
21
import Iter "mo:base/Iter";
32
import Debug "mo:base/Debug";
4-
import Prelude "mo:base/Prelude";
5-
import RbTree "mo:base/RBTree";
63
import Nat "mo:base/Nat";
74
import Buffer "mo:base/Buffer";
85

@@ -12,9 +9,7 @@ import Fuzz "mo:fuzz";
129
import { BpTree; Cmp } "mo:augmented-btrees";
1310

1411
import MemoryBTree "../../src/MemoryBTree/Base";
15-
import BTreeUtils "../../src/MemoryBTree/BTreeUtils";
16-
import MemoryCmp "../../src/MemoryCmp";
17-
import Blobify "../../src/Blobify";
12+
import TypeUtils "../../src/TypeUtils";
1813

1914
module {
2015
type MemoryBTree = MemoryBTree.MemoryBTree;
@@ -43,9 +38,9 @@ module {
4338
let mem_btree = MemoryBTree.new(?256);
4439
let mem_btree2 = MemoryBTree.new(?256);
4540

46-
let btree_utils = BTreeUtils.createUtils(
47-
BTreeUtils.BigEndian.Nat,
48-
BTreeUtils.Nat,
41+
let btree_utils = MemoryBTree.createUtils(
42+
TypeUtils.BigEndian.Nat,
43+
TypeUtils.Nat,
4944
);
5045

5146
let entries = Buffer.Buffer<(Nat, Nat)>(limit);
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import Iter "mo:base/Iter";
2+
import Debug "mo:base/Debug";
3+
import Buffer "mo:base/Buffer";
4+
import Text "mo:base/Text";
5+
import Nat "mo:base/Nat";
6+
7+
import Bench "mo:bench";
8+
import Fuzz "mo:fuzz";
9+
import MotokoStableBTree "mo:MotokoStableBTree/BTree";
10+
11+
import MemoryBTree "../../src/MemoryBTree/Base";
12+
import TypeUtils "../../src/TypeUtils";
13+
import Int8Cmp "../../src/TypeUtils/Int8Cmp";
14+
15+
module {
16+
17+
type MemoryBTree = MemoryBTree.MemoryBTree;
18+
type TypeUtils<K> = TypeUtils.TypeUtils<K>;
19+
type Buffer<T> = Buffer.Buffer<T>;
20+
21+
public func init() : Bench.Bench {
22+
let fuzz = Fuzz.fromSeed(0xdeadbeef);
23+
24+
let bench = Bench.Bench();
25+
bench.name("Comparing B+Tree and Memory B+Tree with different serialization formats and comparison functions");
26+
bench.description("Benchmarking the performance with 10k entries");
27+
28+
bench.rows([
29+
"Memory B+Tree - Text (#BlobCmp)",
30+
"Memory B+Tree - Text (#GenCmp)",
31+
"Memory B+Tree - Candid Text (#BlobCmp)",
32+
"Memory B+Tree - Candid Text (#GenCmp)",
33+
"Memory B+Tree - Nat (#BlobCmp)",
34+
"Memory B+Tree - Nat (#GenCmp)",
35+
"Memory B+Tree - Candid Nat (#GenCmp)",
36+
]);
37+
38+
bench.cols([
39+
"insert()",
40+
"get()",
41+
"replace()",
42+
"entries()",
43+
// "scan()",
44+
"remove()",
45+
]);
46+
47+
let limit = 10_000;
48+
49+
let { n64conv; tconv } = MotokoStableBTree;
50+
51+
let tconv_10 = tconv(10);
52+
53+
let mem_btree_text_gen_cmp = MemoryBTree.new(?128);
54+
let mem_btree_text_blob_cmp = MemoryBTree.new(?128);
55+
let mem_btree_candid_text_gen_cmp = MemoryBTree.new(?128);
56+
let mem_btree_candid_text_blob_cmp = MemoryBTree.new(?128);
57+
58+
let mem_btree_nat_gen_cmp = MemoryBTree.new(?128);
59+
let mem_btree_nat_blob_cmp = MemoryBTree.new(?128);
60+
let mem_btree_candid_nat_gen_cmp = MemoryBTree.new(?128);
61+
let mem_btree_candid_nat_blob_cmp = MemoryBTree.new(?128);
62+
63+
let entries = Buffer.Buffer<(Text, Text)>(limit);
64+
let nat_entries = Buffer.Buffer<(Nat, Nat)>(limit);
65+
// let replacements = Buffer.Buffer<(Text, Text)>(limit);
66+
67+
for (i in Iter.range(0, limit - 1)) {
68+
let key = fuzz.text.randomAlphabetic(10);
69+
70+
entries.add((key, key));
71+
72+
let n = fuzz.nat.randomRange(0, limit ** 2);
73+
nat_entries.add((n, n));
74+
75+
// let replace_val = fuzz.text.randomAlphabetic(10);
76+
77+
// replacements.add((key, key));
78+
};
79+
80+
let sorted = Buffer.clone(entries);
81+
sorted.sort(func(a, b) = Text.compare(a.0, b.0));
82+
83+
func run_bench<K, V>(name : Text, category : Text, mem_btree : MemoryBTree, btree_utils : MemoryBTree.BTreeUtils<K, V>, entries : Buffer<(K, V)>, equal : (V, V) -> Bool) {
84+
switch (category) {
85+
case ("insert()") {
86+
for ((key, val) in entries.vals()) {
87+
ignore MemoryBTree.insert<K, V>(mem_btree, btree_utils, key, val);
88+
};
89+
};
90+
case ("replace()") {
91+
for ((key, val) in entries.vals()) {
92+
ignore MemoryBTree.insert(mem_btree, btree_utils, key, val);
93+
};
94+
};
95+
case ("get()") {
96+
for (i in Iter.range(0, limit - 1)) {
97+
let (key, val) = entries.get(i);
98+
let ?v = MemoryBTree.get(mem_btree, btree_utils, key);
99+
assert equal(val, v);
100+
};
101+
};
102+
case ("entries()") {
103+
for (kv in MemoryBTree.entries(mem_btree, btree_utils)) {
104+
ignore kv;
105+
};
106+
};
107+
case ("scan()") {};
108+
case ("remove()") {
109+
for ((k, v) in entries.vals()) {
110+
ignore MemoryBTree.remove(mem_btree, btree_utils, k);
111+
};
112+
};
113+
case (_) {
114+
Debug.trap("Should not reach with name = " # debug_show name # " and category = " # debug_show category);
115+
};
116+
};
117+
};
118+
119+
let btree_utils = MemoryBTree.createUtils(TypeUtils.Text, TypeUtils.Text);
120+
let gen_cmp_text_utils = MemoryBTree.createUtils({ TypeUtils.Text with cmp = #GenCmp(Int8Cmp.Text) }, TypeUtils.Text);
121+
122+
let candid_text_utils = MemoryBTree.createUtils(TypeUtils.Candid.Text, TypeUtils.Candid.Text);
123+
let candid_text_gen_cmp_utils = MemoryBTree.createUtils({ TypeUtils.Candid.Text with cmp = #GenCmp(Int8Cmp.Text) }, TypeUtils.Candid.Text);
124+
125+
let nat_btree_utils = MemoryBTree.createUtils(TypeUtils.BigEndian.Nat, TypeUtils.BigEndian.Nat);
126+
let nat_gen_cmp_utils = MemoryBTree.createUtils(
127+
{ TypeUtils.BigEndian.Nat with cmp = #GenCmp(Int8Cmp.Nat) },
128+
TypeUtils.BigEndian.Nat,
129+
);
130+
131+
let candid_nat_utils = MemoryBTree.createUtils(TypeUtils.Candid.Nat, TypeUtils.Candid.Nat);
132+
133+
bench.runner(
134+
func(col, row) = switch (col, row) {
135+
136+
case ("Memory B+Tree - Text (#BlobCmp)", category) {
137+
run_bench("Memory B+Tree", category, mem_btree_text_blob_cmp, btree_utils, entries, Text.equal);
138+
};
139+
140+
case ("Memory B+Tree - Text (#GenCmp)", category) {
141+
run_bench("Memory B+Tree", category, mem_btree_text_gen_cmp, gen_cmp_text_utils, entries, Text.equal);
142+
};
143+
144+
case ("Memory B+Tree - Candid Text (#BlobCmp)", category) {
145+
run_bench("Memory B+Tree", category, mem_btree_candid_text_blob_cmp, candid_text_utils, entries, Text.equal);
146+
};
147+
148+
case ("Memory B+Tree - Candid Text (#GenCmp)", category) {
149+
run_bench("Memory B+Tree", category, mem_btree_candid_text_gen_cmp, candid_text_gen_cmp_utils, entries, Text.equal);
150+
};
151+
152+
case ("Memory B+Tree - Nat (#BlobCmp)", category) {
153+
run_bench("Memory B+Tree", category, mem_btree_nat_blob_cmp, nat_btree_utils, nat_entries, Nat.equal);
154+
};
155+
156+
case ("Memory B+Tree - Nat (#GenCmp)", category) {
157+
run_bench<Nat, Nat>("Memory B+Tree", category, mem_btree_nat_gen_cmp, nat_gen_cmp_utils, nat_entries, Nat.equal);
158+
};
159+
160+
case ("Memory B+Tree - Candid Nat (#GenCmp)", category) {
161+
run_bench("Memory B+Tree", category, mem_btree_candid_nat_gen_cmp, candid_nat_utils, nat_entries, Nat.equal);
162+
};
163+
case (_) {
164+
Debug.trap("Should not reach with row = " # debug_show row # " and col = " # debug_show col);
165+
};
166+
}
167+
);
168+
169+
bench;
170+
};
171+
};

0 commit comments

Comments
 (0)