Skip to content

Commit 0431940

Browse files
Use Rc to avoid clone() BasicBlock (nexus-xyz#421)
* Optimize Vec clone by using Rc for shared data: 20% of the time is wasted on basic_block_cache copies
1 parent d13615d commit 0431940

File tree

1 file changed

+11
-8
lines changed

1 file changed

+11
-8
lines changed

vm/src/emulator/executor.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ use rangemap::RangeMap;
158158
use std::{
159159
cmp::max,
160160
collections::{BTreeMap, HashMap, HashSet, VecDeque},
161+
rc::Rc,
161162
};
162-
163163
#[derive(Debug, Default)]
164164
pub struct Executor {
165165
// The CPU
@@ -178,7 +178,7 @@ pub struct Executor {
178178
basic_block_ref_cache: RangeMap<u32, u32>,
179179

180180
// Basic block cache to improve performance
181-
basic_block_cache: BTreeMap<u32, BasicBlockEntry>,
181+
basic_block_cache: BTreeMap<u32, Rc<BasicBlockEntry>>,
182182

183183
// The base address of the program
184184
base_address: u32,
@@ -275,7 +275,7 @@ pub trait Emulator {
275275
///
276276
/// # Returns
277277
/// if success, return a `BasicBlockEntry` starting at the current PC.
278-
fn fetch_block(&mut self, pc: u32) -> Result<BasicBlockEntry>;
278+
fn fetch_block(&mut self, pc: u32) -> Result<Rc<BasicBlockEntry>>;
279279

280280
/// Return a reference to the internal executor component used by the emulator.
281281
fn get_executor(&self) -> &Executor;
@@ -623,7 +623,7 @@ impl Emulator for HarvardEmulator {
623623
///
624624
/// # Returns
625625
/// if success, return a `BasicBlockEntry` starting at the current PC.
626-
fn fetch_block(&mut self, pc: u32) -> Result<BasicBlockEntry> {
626+
fn fetch_block(&mut self, pc: u32) -> Result<Rc<BasicBlockEntry>> {
627627
if let Some(start) = self.executor.basic_block_ref_cache.get(&pc) {
628628
return Ok(self.executor.basic_block_cache.get(start).unwrap().clone());
629629
}
@@ -633,8 +633,11 @@ impl Emulator for HarvardEmulator {
633633
Err(VMErrorKind::VMOutOfInstructions)?
634634
}
635635

636-
let entry = BasicBlockEntry::new(pc, block);
637-
let _ = self.executor.basic_block_cache.insert(pc, entry.clone());
636+
let entry = Rc::new(BasicBlockEntry::new(pc, block));
637+
let _ = self
638+
.executor
639+
.basic_block_cache
640+
.insert(pc, Rc::clone(&entry));
638641

639642
self.executor
640643
.basic_block_ref_cache
@@ -1080,7 +1083,7 @@ impl Emulator for LinearEmulator {
10801083
///
10811084
/// # Returns
10821085
/// if success, return a `BasicBlockEntry` starting at the current PC.
1083-
fn fetch_block(&mut self, pc: u32) -> Result<BasicBlockEntry> {
1086+
fn fetch_block(&mut self, pc: u32) -> Result<Rc<BasicBlockEntry>> {
10841087
if let Some(start) = self.executor.basic_block_ref_cache.get(&pc) {
10851088
return Ok(self.executor.basic_block_cache.get(start).unwrap().clone());
10861089
}
@@ -1094,7 +1097,7 @@ impl Emulator for LinearEmulator {
10941097
Err(VMErrorKind::VMOutOfInstructions)?
10951098
}
10961099

1097-
let entry = BasicBlockEntry::new(pc, block);
1100+
let entry = Rc::new(BasicBlockEntry::new(pc, block));
10981101
let _ = self.executor.basic_block_cache.insert(pc, entry.clone());
10991102

11001103
self.executor

0 commit comments

Comments
 (0)