Completed: ICDevs.org - Bounty 24 - StableBtree Mokoko - up to $10k

I’ve merged the changes I’ve done to use the Region instead of the ExperimentalStableMemory in the trunk. I made a few changes in the interfaces of the lib, I was inspired by the Map from @ZhenyaUsenko. The intended usage:

  import BTree "mo:StableBTree/BTree"

  // Arbitrary use of (Nat32, Text) for (key, value) types
  let n32conv = BTree.n32conv;
  let tconv = BTree.tconv(64); // Max 16 characters
  stable let _btree = BTree.new<Nat32, Text>(n32conv, tconv);

  let old = BTree.put(_btree, n32conv, 0, tconv, "hello");
  let new = BTree.get(_btree, n32conv, 0, tconv);
  let size = BTree.size(_btree);

  assert Option.isNull(old);
  assert Option.isSome(new);
  assert size == 1;

Where the types are as follow:

type BTree<K, V> = {
    region: Region;
    key_nonce: K;
    value_nonce: V;
  };

type BytesConverter<T> = {
    from_bytes: (Blob) -> T;
    to_bytes: (T) -> Blob;
    max_size: Nat32;
    nonce: T;
  };

The “nonces” (shall probably be renamed) are only useful to keep the initial template parameters, so that when a BTree is loaded from stable memory later, the compilation prevents loading it with different template parameters than the original one. It’s kind of a trick, but I don’t know how else to do to support template parameters otherwise.
The max_size is used at the initialization of the btree and directly stored in stable memory. If you every give a greater max size later it will have no effect, and inserting a key/value with a greater size than the original one will still trap.
If you guys have better ideas please share.

I’d like to create benchmarks for the lib before releasing it on mops. @ZhenyaUsenko I was wondering how did you come up with your performance metrics for your stable map?

2 Likes