Is there any way to mutate the value inside IC-Stable-Structures BTreeMap?

I’ve got two canisters which index ICP transactions - one uses the IC stable memory (ic_stable_memory - Rust) by senior.joinu. This works well and can update up to 10,000 entries in the SBTreeMap without hitting the canister instruction limit (using get_mut method on the map).

The IC Stable Structures canister however can’t even process 2000 without hitting the instruction limit. I think this is down to the fact that (unless I’m missing something) to update a value using the IC Stable Structures version, you first need to get the value, copy it/ modify it and then re-insert it?

Are there any plans to add a get_mut method to IC-Stable-Structures BTreeMap?

Thanks Nathan for sharing this observation. I agree there’s a long way to go as far as the performance of stable structures.

This is actually not the performance bottleneck currently. As in, introducing a get_mut wouldn’t change the performance in a meaningful way. The performance bottleneck is in loading (deserializing) and saving (serializing) BTree nodes. If we cache nodes so we don’t need to deserialize them every time we access them, I expect the performance to improve significantly. I filed a ticket to track this.

Can you share the type of the entries you’re modifying? We can then use that to do some benchmarking.

1 Like

Ah ok, I was just guessing it was the double read of the map. I’m using a fairly large struct which is 3 layers deep. It’s a lot to load/ save and probably is making this issue a LOT worse. I could spit the data into separate BTreeMaps but I like the idea of being able to pull all the Account data in a single lookup.

The main map is <key: String, value: AccountData>

pub struct AccountData {
    pub overview: Overview,
    pub data: IndexData,
}

 pub struct Overview {
    pub first_active: u64,
    pub last_active: u64,
    pub sent: (u32, Nat), // count, value 
    pub received: (u32, Nat), // count, value
    pub balance: Nat, 
 }

pub struct IndexData {
    pub links: BTreeMap<u64, LinkData>,
    pub blocks: Vec<u64>
}

pub struct LinkData {
     pub linked_from: u64,
     pub linked_id: u64,
     pub number_txs: u32,
     pub gross: Nat,
     pub net: i128
}