From 6007855bc81cb3e53f82bfdc90cc7d7f63f790d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C5=A1a=20Tomi=C4=87?= Date: Wed, 18 Mar 2026 18:39:21 +0100 Subject: [PATCH] perf: cache BaseVec len in Cell to avoid stable memory reads BaseVec::len() previously read from stable memory on every call. MinHeap calls len() O(log n) times per push/pop via sift_up/sift_down bounds checks, making this a significant overhead. Cache the length in a Cell and keep it in sync with the persisted value. --- src/base_vec.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/base_vec.rs b/src/base_vec.rs index 5e6eeea2..cd0aa729 100644 --- a/src/base_vec.rs +++ b/src/base_vec.rs @@ -37,6 +37,7 @@ use crate::{ Memory, Storable, }; use std::borrow::{Borrow, Cow}; +use std::cell::Cell; use std::cmp::min; use std::fmt; use std::marker::PhantomData; @@ -95,6 +96,7 @@ impl std::error::Error for InitError {} pub struct BaseVec { memory: M, + cached_len: Cell, _marker: PhantomData, } @@ -117,6 +119,7 @@ impl BaseVec { Self::write_header(&header, &memory)?; Ok(Self { memory, + cached_len: Cell::new(0), _marker: PhantomData, }) } @@ -148,6 +151,7 @@ impl BaseVec { Ok(Self { memory, + cached_len: Cell::new(header.len), _marker: PhantomData, }) } @@ -168,7 +172,7 @@ impl BaseVec { /// /// Complexity: O(1) pub fn len(&self) -> u64 { - read_u64(&self.memory, Address::from(LEN_OFFSET)) + self.cached_len.get() } /// Sets the item at the specified index to the specified value. @@ -254,6 +258,7 @@ impl BaseVec { /// Sets the vector's length. fn set_len(&self, new_len: u64) { write_u64(&self.memory, Address::from(LEN_OFFSET), new_len); + self.cached_len.set(new_len); } /// Writes the size of the item at the specified offset.