Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure pinning a contract that is already pinned is cheap #808

Merged
merged 2 commits into from
Mar 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions packages/vm/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ where
/// pinned cache.
/// If the given ID is not found, or the content does not match the hash (=ID), an error is returned.
pub fn pin(&mut self, checksum: &Checksum) -> VmResult<()> {
if self.pinned_memory_cache.has(checksum) {
return Ok(());
}

// Try to get module from the memory cache
if let Some(module) = self.memory_cache.load(checksum)? {
self.stats.hits_memory_cache += 1;
Expand Down Expand Up @@ -831,8 +835,19 @@ mod tests {
assert_eq!(cache.stats().hits_fs_cache, 1);
assert_eq!(cache.stats().misses, 0);

// pin
let _ = cache.pin(&id);
// first pin hits memory cache
cache.pin(&id).unwrap();
assert_eq!(cache.stats().hits_pinned_memory_cache, 0);
assert_eq!(cache.stats().hits_memory_cache, 1);
assert_eq!(cache.stats().hits_fs_cache, 1);
assert_eq!(cache.stats().misses, 0);

// consecutive pins are no-ops
cache.pin(&id).unwrap();
assert_eq!(cache.stats().hits_pinned_memory_cache, 0);
assert_eq!(cache.stats().hits_memory_cache, 1);
assert_eq!(cache.stats().hits_fs_cache, 1);
assert_eq!(cache.stats().misses, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice tests.


// check pinned
let backend = mock_backend(&[]);
Expand All @@ -843,7 +858,7 @@ mod tests {
assert_eq!(cache.stats().misses, 0);

// unpin
let _ = cache.unpin(&id);
cache.unpin(&id).unwrap();

// verify unpinned
let backend = mock_backend(&[]);
Expand All @@ -854,10 +869,10 @@ mod tests {
assert_eq!(cache.stats().misses, 0);

// unpin again has no effect
let _ = cache.unpin(&id).unwrap();
cache.unpin(&id).unwrap();

// unpin non existent id has no effect
let non_id = Checksum::generate(b"non_existent");
let _ = cache.unpin(&non_id).unwrap();
cache.unpin(&non_id).unwrap();
}
}
36 changes: 36 additions & 0 deletions packages/vm/src/modules/pinned_memory_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ impl PinnedMemoryCache {
None => Ok(None),
}
}

/// Returns true if and only if this cache has an entry identified by the given checksum
pub fn has(&self, checksum: &Checksum) -> bool {
self.modules.contains_key(checksum)
}
}

#[cfg(test)]
Expand Down Expand Up @@ -94,4 +99,35 @@ mod tests {
assert_eq!(result[0].unwrap_i32(), 43);
}
}

#[test]
fn has_works() {
let mut cache = PinnedMemoryCache::new();

// Create module
let wasm = wat::parse_str(
r#"(module
(type $t0 (func (param i32) (result i32)))
(func $add_one (export "add_one") (type $t0) (param $p0 i32) (result i32)
get_local $p0
i32.const 1
i32.add)
)"#,
)
.unwrap();
let checksum = Checksum::generate(&wasm);

assert_eq!(cache.has(&checksum), false);

// Add
let original = compile(&wasm, None).unwrap();
cache.store(&checksum, original).unwrap();

assert_eq!(cache.has(&checksum), true);

// Remove
cache.remove(&checksum).unwrap();

assert_eq!(cache.has(&checksum), false);
}
}