Skip to content

Commit 25eaa8a

Browse files
authored
perf: Replace BTreeMap with constant vector in MemoryManager (#240)
Since we can have maximum 255 memories, we can store those cheaply in a `Vec` and save time during the lookup.
1 parent 6344f6e commit 25eaa8a

File tree

2 files changed

+28
-38
lines changed

2 files changed

+28
-38
lines changed

canbench_results.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ benches:
7373
scopes: {}
7474
btreemap_get_blob_512_1024_v2_mem_manager:
7575
total:
76-
instructions: 3164909208
76+
instructions: 3093928908
7777
heap_increase: 0
7878
stable_memory_increase: 0
7979
scopes: { }
@@ -139,7 +139,7 @@ benches:
139139
scopes: { }
140140
btreemap_get_u64_u64_v2_mem_manager:
141141
total:
142-
instructions: 673752904
142+
instructions: 619036864
143143
heap_increase: 0
144144
stable_memory_increase: 0
145145
scopes: {}
@@ -223,7 +223,7 @@ benches:
223223
scopes: { }
224224
btreemap_insert_blob_1024_512_v2_mem_manager:
225225
total:
226-
instructions: 6292667075
226+
instructions: 6188501297
227227
heap_increase: 0
228228
stable_memory_increase: 256
229229
scopes: {}
@@ -379,7 +379,7 @@ benches:
379379
scopes: {}
380380
btreemap_insert_u64_u64_mem_manager:
381381
total:
382-
instructions: 1019612837
382+
instructions: 937850849
383383
heap_increase: 0
384384
stable_memory_increase: 0
385385
scopes: { }
@@ -625,13 +625,13 @@ benches:
625625
scopes: {}
626626
memory_manager_grow:
627627
total:
628-
instructions: 349384162
628+
instructions: 346632000
629629
heap_increase: 2
630630
stable_memory_increase: 32000
631631
scopes: {}
632632
memory_manager_overhead:
633633
total:
634-
instructions: 1182116368
634+
instructions: 1182056741
635635
heap_increase: 0
636636
stable_memory_increase: 8320
637637
scopes: {}
@@ -661,7 +661,7 @@ benches:
661661
scopes: {}
662662
vec_get_blob_4_mem_manager:
663663
total:
664-
instructions: 14476122
664+
instructions: 12856122
665665
heap_increase: 0
666666
stable_memory_increase: 0
667667
scopes: { }
@@ -673,7 +673,7 @@ benches:
673673
scopes: { }
674674
vec_get_blob_64_mem_manager:
675675
total:
676-
instructions: 24146389
676+
instructions: 22526389
677677
heap_increase: 0
678678
stable_memory_increase: 0
679679
scopes: {}

src/memory_manager.rs

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ use crate::{
4747
};
4848
use std::cell::RefCell;
4949
use std::cmp::min;
50-
use std::collections::BTreeMap;
5150
use std::rc::Rc;
5251

5352
const MAGIC: &[u8; 3] = b"MGR";
@@ -228,7 +227,7 @@ struct MemoryManagerInner<M: Memory> {
228227
memory_sizes_in_pages: [u64; MAX_NUM_MEMORIES as usize],
229228

230229
// A map mapping each managed memory to the bucket ids that are allocated to it.
231-
memory_buckets: BTreeMap<MemoryId, Vec<BucketId>>,
230+
memory_buckets: Vec<Vec<BucketId>>,
232231
}
233232

234233
impl<M: Memory> MemoryManagerInner<M> {
@@ -255,7 +254,7 @@ impl<M: Memory> MemoryManagerInner<M> {
255254
memory,
256255
allocated_buckets: 0,
257256
memory_sizes_in_pages: [0; MAX_NUM_MEMORIES as usize],
258-
memory_buckets: BTreeMap::new(),
257+
memory_buckets: vec![vec![]; MAX_NUM_MEMORIES as usize],
259258
bucket_size_in_pages,
260259
};
261260

@@ -285,13 +284,10 @@ impl<M: Memory> MemoryManagerInner<M> {
285284
MAX_NUM_BUCKETS as usize,
286285
);
287286

288-
let mut memory_buckets = BTreeMap::new();
287+
let mut memory_buckets = vec![vec![]; MAX_NUM_MEMORIES as usize];
289288
for (bucket_idx, memory) in buckets.into_iter().enumerate() {
290289
if memory != UNALLOCATED_BUCKET_MARKER {
291-
memory_buckets
292-
.entry(MemoryId(memory))
293-
.or_insert_with(Vec::new)
294-
.push(BucketId(bucket_idx as u16));
290+
memory_buckets[memory as usize].push(BucketId(bucket_idx as u16));
295291
}
296292
}
297293

@@ -336,14 +332,12 @@ impl<M: Memory> MemoryManagerInner<M> {
336332
return -1;
337333
}
338334

335+
let memory_bucket = &mut self.memory_buckets[id.0 as usize];
339336
// Allocate new buckets as needed.
337+
memory_bucket.reserve(new_buckets_needed as usize);
340338
for _ in 0..new_buckets_needed {
341339
let new_bucket_id = BucketId(self.allocated_buckets);
342-
343-
self.memory_buckets
344-
.entry(id)
345-
.or_default()
346-
.push(new_bucket_id);
340+
memory_bucket.push(new_bucket_id);
347341

348342
// Write in stable store that this bucket belongs to the memory with the provided `id`.
349343
write(
@@ -407,12 +401,9 @@ impl<M: Memory> MemoryManagerInner<M> {
407401
}
408402

409403
// Initializes a [`BucketIterator`].
410-
fn bucket_iter(&self, id: MemoryId, offset: u64, length: usize) -> BucketIterator {
404+
fn bucket_iter(&self, MemoryId(id): MemoryId, offset: u64, length: usize) -> BucketIterator {
411405
// Get the buckets allocated to the given memory id.
412-
let buckets = match self.memory_buckets.get(&id) {
413-
Some(s) => s.as_slice(),
414-
None => &[],
415-
};
406+
let buckets = self.memory_buckets[id as usize].as_slice();
416407

417408
BucketIterator {
418409
virtual_segment: Segment {
@@ -548,7 +539,6 @@ fn bucket_allocations_address(id: BucketId) -> Address {
548539
#[cfg(test)]
549540
mod test {
550541
use super::*;
551-
use maplit::btreemap;
552542
use proptest::prelude::*;
553543

554544
const MAX_MEMORY_IN_PAGES: u64 = MAX_NUM_BUCKETS * BUCKET_SIZE_IN_PAGES;
@@ -577,12 +567,11 @@ mod test {
577567
memory.read(0, &mut bytes);
578568
assert_eq!(bytes, vec![1, 2, 3]);
579569

580-
assert_eq!(
581-
mem_mgr.inner.borrow().memory_buckets,
582-
btreemap! {
583-
MemoryId(0) => vec![BucketId(0)]
584-
}
585-
);
570+
assert_eq!(mem_mgr.inner.borrow().memory_buckets[0], vec![BucketId(0)]);
571+
572+
assert!(mem_mgr.inner.borrow().memory_buckets[1..]
573+
.iter()
574+
.all(|x| x.is_empty()));
586575
}
587576

588577
#[test]
@@ -599,13 +588,14 @@ mod test {
599588
assert_eq!(memory_1.size(), 1);
600589

601590
assert_eq!(
602-
mem_mgr.inner.borrow().memory_buckets,
603-
btreemap! {
604-
MemoryId(0) => vec![BucketId(0)],
605-
MemoryId(1) => vec![BucketId(1)],
606-
}
591+
&mem_mgr.inner.borrow().memory_buckets[..2],
592+
&[vec![BucketId(0)], vec![BucketId(1)],]
607593
);
608594

595+
assert!(mem_mgr.inner.borrow().memory_buckets[2..]
596+
.iter()
597+
.all(|x| x.is_empty()));
598+
609599
memory_0.write(0, &[1, 2, 3]);
610600
memory_0.write(0, &[1, 2, 3]);
611601
memory_1.write(0, &[4, 5, 6]);

0 commit comments

Comments
 (0)