Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The original, unoptimized stable B-Tree (with new metering) (c.f. #97) #99

Draft
wants to merge 46 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
ba18267
Another Stable B-Tree.
matthewhammer Sep 21, 2023
1672565
add canister for StableBTree
matthewhammer Sep 21, 2023
5e3279b
add lines to scripts.
matthewhammer Sep 21, 2023
5517ad1
add stable benchmark
chenyan-dfinity Sep 30, 2023
4d75426
fix
chenyan-dfinity Sep 30, 2023
16789ef
adjust to 800k
chenyan-dfinity Sep 30, 2023
a66115e
fix
chenyan-dfinity Sep 30, 2023
f1ed547
600k
chenyan-dfinity Sep 30, 2023
42cbdc5
fix
chenyan-dfinity Sep 30, 2023
15551ee
fix
chenyan-dfinity Sep 30, 2023
ce9dc97
vec_stable
chenyan-dfinity Sep 30, 2023
bf08e4f
heap_stable
chenyan-dfinity Sep 30, 2023
ef7c7db
readme
chenyan-dfinity Oct 1, 2023
a086a5e
fix
chenyan-dfinity Oct 1, 2023
3b6a80d
Merge remote-tracking branch 'origin/main' into matthew/sardariussBTree
chenyan-dfinity Oct 2, 2023
35a1afe
Merge remote-tracking branch 'origin/stable' into matthew/sardariussB…
chenyan-dfinity Oct 2, 2023
233ced1
rename
chenyan-dfinity Oct 2, 2023
2c197ea
fix
chenyan-dfinity Oct 2, 2023
6f0bc84
fix
chenyan-dfinity Oct 4, 2023
2c6ea7c
Merge remote-tracking branch 'origin/main' into matthew/sardariussBTree
chenyan-dfinity Oct 4, 2023
8120365
fix
chenyan-dfinity Oct 4, 2023
5045744
fix
chenyan-dfinity Oct 4, 2023
c8764a6
change fork for stable btree to claudio's optimized one
crusso Oct 5, 2023
27e93e6
Update mops.template.toml
crusso Oct 5, 2023
0071d15
target branch claudio
crusso Oct 5, 2023
c2880ec
repoint libraries
crusso Oct 5, 2023
a8b76f1
Merge branch 'claudio/sardariussBTree' into claudio/sardariussBTree-c…
crusso Oct 5, 2023
1e911af
try something new
crusso Oct 5, 2023
d9235de
hackity hack
crusso Oct 5, 2023
cdcbe74
try something new
crusso Oct 5, 2023
4fcdb9a
hackity hack
crusso Oct 5, 2023
da927e3
adjust to API changes
crusso Oct 5, 2023
2a44e70
adjust to API changes
crusso Oct 5, 2023
f1c7f96
disablec crashing rust test
crusso Oct 5, 2023
7e664fb
disablec crashing rust test
crusso Oct 5, 2023
3fcb919
focus on collections
crusso Oct 6, 2023
29feadf
focus on collections
crusso Oct 6, 2023
ab661cf
Update collections/motoko/mops.template.toml
crusso Oct 6, 2023
3031697
re-enable btreemap_stable_rs
crusso Oct 6, 2023
495a8b6
Merge branch 'claudio/sardariussBTree-claudio' of github.com:dfinity/…
crusso Oct 6, 2023
b1849cf
re-enable btreemap_stable_rs
crusso Oct 6, 2023
17c9f65
Merge branch 'claudio/sardariussBTree' into claudio/sardariussBTree-c…
crusso Oct 6, 2023
c100f6e
Merge remote-tracking branch 'origin/main' into claudio/sardariussBTr…
chenyan-dfinity Oct 11, 2023
f2f0bcc
fix
chenyan-dfinity Oct 11, 2023
54bf1af
use new metering
chenyan-dfinity Oct 13, 2023
c656bde
compare against unoptimized btree
crusso Oct 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
APPS = dapps collections crypto pub-sub heartbeat motoko
#APPS = dapps collections crypto pub-sub heartbeat motoko
APPS = collections

all:
$(foreach test_dir,$(APPS),make -C $(test_dir) &&) true
Expand Down
5 changes: 3 additions & 2 deletions collections/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ We use the same random number generator with fixed seed to ensure that all colle
the same elements, and the queries are exactly the same. Below we explain the measurements of each column in the table:

* generate 1m. Insert 1m Nat64 integers into the collection. For Motoko collections, it usually triggers the GC; the rest of the column are not likely to trigger GC.
* max mem. For Motoko, it reports `rts_max_heap_size` after `generate` call; For Rust, it reports the Wasm's memory page * 32Kb.
* max mem. For Motoko, it reports `rts_max_heap_size` after `generate` call; For Rust, it reports the Wasm's memory page * 64Kb; For stable benchmarks, it reports the region size of the stable memory storing the map.
* batch_get 50. Find 50 elements from the collection.
* batch_put 50. Insert 50 elements to the collection.
* batch_remove 50. Remove 50 elements from the collection.
* upgrade. Upgrade the canister with the same Wasm module. For non-stable benchmarks, the map state is persisted by serializing and deserializing states into stable memory. For stable benchmarks, the upgrade takes no cycles, as the state is already in the stable memory.
* upgrade. Upgrade the canister with the same Wasm module. For non-stable benchmarks, the map state is persisted by serializing and deserializing states into stable memory. For stable benchmarks, the upgrade only needs to initialize the metadata, as the state is already in the stable memory.

## **💎 Takeaways**

Expand All @@ -33,6 +33,7 @@ the same elements, and the queries are exactly the same. Below we explain the me
> * The stable benchmarks are much more expensive than their non-stable counterpart, because the stable memory API is much more expensive. The benefit is that they get fast upgrade. The upgrade still needs to parse the metadata when initializing the upgraded Wasm module.
> * `hashmap` uses amortized data structure. When the initial capacity is reached, it has to copy the whole array, thus the cost of `batch_put 50` is much higher than other data structures.
> * `btree` comes from [mops.one/stableheapbtreemap](https://mops.one/stableheapbtreemap).
> * `btree_stable` comes from [github.com/sardariuss](https://github.com/sardariuss/MotokoStableBTree).
> * `zhenya_hashmap` comes from [mops.one/map](https://mops.one/map).
> * `vector` comes from [mops.one/vector](https://mops.one/vector). Compare with `buffer`, `put` has better worst case time and space complexity ($O(\sqrt{n})$ vs $O(n)$); `get` has a slightly larger constant overhead.
> * `hashmap_rs` uses the `fxhash` crate, which is the same as `std::collections::HashMap`, but with a deterministic hasher. This ensures reproducible result.
Expand Down
4 changes: 4 additions & 0 deletions collections/motoko/dfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
"vector": {
"type": "motoko",
"main": "src/vector.mo"
},
"btreemap_stable": {
"type": "motoko",
"main": "src/btreemap_stable.mo"
}
},
"defaults": {
Expand Down
3 changes: 2 additions & 1 deletion collections/motoko/mops.template.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[dependencies]
base = "https://github.com/dfinity/motoko-base#moc-$MOC_VERSION"
base = "$MOC_VERSION"
stableheapbtreemap = "1.3.0"
map = "9.0.0"
splay = "0.1.0"
vector = "0.2.0"
StableBTree = "https://github.com/crusso/MotokoStableBTree"
55 changes: 55 additions & 0 deletions collections/motoko/src/btreemap_stable.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import Nat64 "mo:base/Nat64";
import Iter "mo:base/Iter";
import Option "mo:base/Option";
import Region "mo:base/Region";

import Random "random";
import Profiling "../../../utils/motoko/Profiling";

import BytesConverter "mo:StableBTree/modules/bytesConverter";
import Map "mo:StableBTree/modules/btreemap";
import Memory "mo:StableBTree/modules/memory";

actor {
stable let profiling = Profiling.init();
stable var region = Region.new();
let n64conv = BytesConverter.n64conv;
var map = Map.init<Nat64, Nat64>(
Memory.RegionMemory(region),
n64conv,
n64conv
);

let rand = Random.new(null, 42);

public func generate(size : Nat32) : async () {
let rand = Random.new(?size, 1);
let iter = Iter.map<Nat64, (Nat64, Nat64)>(rand, func x = (x, x));
for ((k, v) in iter) {
ignore map.insert(k, n64conv, v, n64conv);
};
};
public query func get_mem() : async (Nat, Nat, Nat) {
let size = Nat64.toNat(Region.size(region)) * 65536;
(size, size, size)
};
public func batch_get(n : Nat) : async () {
for (_ in Iter.range(1, n)) {
let x = Option.get<Nat64>(rand.next(), 0);
ignore map.get(x, n64conv, n64conv);
};
};
public func batch_put(n : Nat) : async () {
for (_ in Iter.range(1, n)) {
let k = Option.get<Nat64>(rand.next(), 0);
ignore map.insert(k, n64conv, k, n64conv);
};
};
public func batch_remove(n : Nat) : async () {
let rand = Random.new(null, 1);
for (_ in Iter.range(1, n)) {
let x = Option.get<Nat64>(rand.next(), 0);
ignore map.remove(x, n64conv, n64conv);
};
};
};
3 changes: 3 additions & 0 deletions collections/perf.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ let triemap = wasm_profiling("motoko/.dfx/local/canisters/triemap/triemap.wasm",
let rbtree = wasm_profiling("motoko/.dfx/local/canisters/rbtree/rbtree.wasm", mo_config);
let splay = wasm_profiling("motoko/.dfx/local/canisters/splay/splay.wasm", mo_config);
let btree = wasm_profiling("motoko/.dfx/local/canisters/btreemap/btreemap.wasm", mo_config);
let btree_stable = wasm_profiling("motoko/.dfx/local/canisters/btreemap_stable/btreemap_stable.wasm", mo_config);
let zhenya = wasm_profiling("motoko/.dfx/local/canisters/zhenya_hashmap/zhenya_hashmap.wasm", mo_config);
let heap = wasm_profiling("motoko/.dfx/local/canisters/heap/heap.wasm", mo_config);
let buffer = wasm_profiling("motoko/.dfx/local/canisters/buffer/buffer.wasm", mo_config);
Expand Down Expand Up @@ -90,6 +91,8 @@ perf(vector_rs, "vec_rs", init_size, batch_size);
let init_size = 50_000;
let batch_size = 50;
output(file, "\n## Stable structures\n\n| |binary_size|generate 50k|max mem|batch_get 50|batch_put 50|batch_remove 50|upgrade|\n|--:|--:|--:|--:|--:|--:|--:|--:|\n");
perf(btree, "btree", init_size, batch_size);
perf(btree_stable, "btree_stable", init_size, batch_size);
perf(btreemap_rs, "btreemap_rs", init_size, batch_size);
perf(btreemap_stable_rs, "btreemap_stable_rs", init_size, batch_size);
perf(heap_rs, "heap_rs", init_size, batch_size);
Expand Down
6 changes: 3 additions & 3 deletions utils.mk
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ endef
define perf
set -e; \
$(call prepare_perf,$(1)); \
ic-repl ../../$(1)/$(2); \
ic-repl --use-new-metering ../../$(1)/$(2); \
du -h ../../_out
endef

define perf_two
set -e; \
$(call prepare_perf,$(1)); \
ic-repl ../../$(1)/$(2); \
ic-repl ../../$(1)/$(3); \
ic-repl --use-new-metering ../../$(1)/$(2); \
ic-repl --use-new-metering ../../$(1)/$(3); \
du -h ../../_out
endef
Loading