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

Cache wasmer instances and add cache stats #140

Merged
merged 6 commits into from
Jan 31, 2020
Merged

Cache wasmer instances and add cache stats #140

merged 6 commits into from
Jan 31, 2020

Conversation

webmaster128
Copy link
Member

Closes #137

It turns out that reusing a wasmer instance from Instance is much easier than reusing the storage because the storage is needed to create the wasmer context, which makes things very complicated. This leaves the storage question untouched.

Copy link
Member

@ethanfrey ethanfrey left a comment

Choose a reason for hiding this comment

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

Nice improvement.

Made some comments on cleanup, main one is use of recycle so you can't accidentally leak the storage.

Feel free to merge after one round of cleanup.

pub struct CosmCache<S: Storage + 'static, A: Api + 'static> {
wasm_path: PathBuf,
modules: FileSystemCache,
instances: Option<LruCache<WasmHash, Instance<S, A>>>,
instances: Option<LruCache<WasmHash, wasmer_runtime_core::Instance>>,
Copy link
Member

Choose a reason for hiding this comment

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

Ah... that does simplify things, as nothing is bound

@@ -48,6 +59,13 @@ where
modules,
wasm_path,
instances,
stats: Stats {
Copy link
Member

Choose a reason for hiding this comment

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

rust tip:

if you add #[derive(Default)] above the Stats definition, then you get this via Stats::Default()

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks! Done in de489a9

Instance::from_code(&wasm, deps)
}

pub fn store_instance(&mut self, id: &[u8], instance: Instance<S, A>) -> Option<Extern<S, A>> {
if let Some(cache) = &mut self.instances {
let hash = WasmHash::generate(&id);
let storage = instance.take_storage();
let api = instance.api; // copy it
cache.put(hash, instance);
let (wasmer_instance, api) = Instance::recycle(instance);
Copy link
Member

Choose a reason for hiding this comment

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

How about having Instance::recycle return {wasmer_instance, extern} and collapse the take_storage line above and simply the return value?

cache.store_instance(&id, instance2);
let instance3 = cache.get_instance(&id, deps3).unwrap();
cache.store_instance(&id, instance3);
assert_eq!(cache.stats.hits_instance, 2);
Copy link
Member

Choose a reason for hiding this comment

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

Loving these stats. Not just for performance measurements, but to ensure the code is doing what we want.

@@ -74,50 +74,50 @@ pub fn do_human_address<A: Api>(api: A, ctx: &mut Ctx, canonical_ptr: u32, human

/** context data **/

struct ContextData<T: Storage> {
data: Option<T>,
struct ContextData<S: Storage> {
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, good rename. Generally in rust, all single generics are named T by convention. I found <T, U, V> a bit confusing, rather use S, A, etc in the code to make it clearer. Only did that when there were multi-args, but nice here for consistency.


/// Takes ownership of instance and decomposes it into its components.
/// The components we want to preserve are returned, the rest is dropped.
pub fn recycle(instance: Self) -> (wasmer_runtime_core::Instance, A) {
Copy link
Member

Choose a reason for hiding this comment

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

What about adding take_storage in here, which is tied to the wasmer_instance context.
So it fully decomposes all the info we put in.

Copy link
Member Author

Choose a reason for hiding this comment

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

I liked the idea. However, when thinking about it more I figured that this would make Instance construction and Instance::recycle asymmetric. This is because no representation of storage is owned by the instance. I think when we manually group storage and instance using leave_storage, we should also manually ungroup then later.

Copy link
Member

Choose a reason for hiding this comment

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

The usage I see (from the high level) is:

Instance::from_module(&module, deps) or Instance::from_code(&wasm, deps) to construct it. This takes deps: Extern<S, A>.

When freeing, or recycling the instance, I would assume the inverse of something like:

let {wasmer_instance, deps} = instance::recycle();

which should return a comprable deps as when we constructed it.

On another note, I wonder if we can make leave_storage and take_storage private to just the module. On the public side, we could create a new instance with one of the from_xxx() methods, recycle it, or do some queries via instance.with_storage(&|store| { ... }).

This can be another cleanup PR, but I think will simplify the external API and the safety guarantees. (I really like the recycle idea)

Copy link
Member Author

Choose a reason for hiding this comment

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

The usage I see (from the high level) is

oh yeah, right, this way we have symmetry.

On another note, I wonder if we can make leave_storage and take_storage private to just the module.

Jap, that works!

@webmaster128 webmaster128 changed the title Cache wasmer instances and add chache stats Cache wasmer instances and add cache stats Jan 31, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants