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

Create example for limiting memory with Tunables #1730

Merged
merged 5 commits into from
Oct 28, 2020

Conversation

webmaster128
Copy link
Contributor

@webmaster128 webmaster128 commented Oct 16, 2020

Closes #1588

Description

This is an attempt for solving #1360 with the new Tunables API. It could be developed further to address #1588 if you like.

I'd appreciate a code review to ensure I'm on the right track.

Open questions:

  1. Is it expected that I had to add wasmer-vm?
  2. Should I really create a new Target for this use case when engine already has one set?
  3. I used BaseTunables for the base implementation and sticked with Tunables for the trait name, because it makes most sense to me. However, in lib/api/src/tunables.rs it is done the other way round. Any thoughts on the naming issue?
  4. The import collision between wamer::Memory and wasmer_vm::Memory is inconvenient. Can it be avoided or do I do it correctly here?

Review

  • Add a short description of the the change to the CHANGELOG.md file

Comment on lines 2 to 9
use wasmer::{
imports, wat2wasm, Instance, Memory, MemoryError, MemoryType, Module, Pages, Store, TableType,
Tunables as BaseTunables,
};
use wasmer_compiler::Target;
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine::Tunables;
use wasmer_engine_jit::JIT;
use wasmer_vm::{Memory as MemoryTrait, MemoryStyle, Table, TableStyle};
Copy link
Member

Choose a reason for hiding this comment

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

For the example, I think it would be better to get some of the structs directly from Wasmer (so people don't depend on other subpackages).

Suggested change
use wasmer::{
imports, wat2wasm, Instance, Memory, MemoryError, MemoryType, Module, Pages, Store, TableType,
Tunables as BaseTunables,
};
use wasmer_compiler::Target;
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine::Tunables;
use wasmer_engine_jit::JIT;
use wasmer_vm::{Memory as MemoryTrait, MemoryStyle, Table, TableStyle};
use wasmer::{
imports, wat2wasm, Instance, Memory, MemoryError, MemoryType, Module, Pages, Store, TableType,
Tunables, WasmerTunables, Target, Memory, RuntimeMemory, MemoryStyle, RuntimeTable, TableStyle
};
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine_jit::JIT;

This will imply exposing the following structs in the Wasmer API (lib/api/src/lib.rs):

pub use crate::tunables::Tunables as WasmerTunables;

pub use wasmer_engine::Tunables;
pub use wasmer_vm::{Memory as RunnableMemory, MemoryStyle, Table as RunnableTable, TableStyle};

Note: other alternative would be exposing the subcrates as submodules off the API:

Suggested change
use wasmer::{
imports, wat2wasm, Instance, Memory, MemoryError, MemoryType, Module, Pages, Store, TableType,
Tunables as BaseTunables,
};
use wasmer_compiler::Target;
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine::Tunables;
use wasmer_engine_jit::JIT;
use wasmer_vm::{Memory as MemoryTrait, MemoryStyle, Table, TableStyle};
use wasmer::{
imports, wat2wasm, Instance, Memory, MemoryError, MemoryType, Module, Pages, Store, TableType,
Target, Tunables as BaseTunables,
engine::Tunables,
vm::{Memory as MemoryTrait, MemoryStyle, Table, TableStyle};
};
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine_jit::JIT;
pub mod engine {
    pub use wasmer_engine::Tunables;
}
pub mod vm {
    pub use wasmer_vm::{Memory, MemoryStyle, Table, TableStyle};
}

Thoughts @MarkMcCaskey ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I can see either way, for things that conflict in name like Memory namespacing can be a nice way to deal with it, I think expecting people to know about use x as y syntax in Rust is probably not a good assumption (though maybe the error message you get tells you how to fix it), so I'd be more in favor of the public submodule idea than exporting 2 things with the same name at the same scope level.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think expecting people to know about use x as y syntax in Rust is probably not a good assumption (though maybe the error message you get tells you how to fix it)

Agreed. However, in my case the bigger problem was very very confusing error messages about types that are Sized or size not known at compile time when I had Memory (trait) importet and then used Vec<Memory> in the code, which referes to the exported Memory (struct). Took a while to realize there are more than one of those in Wasmer.

Copy link
Member

@syrusakbary syrusakbary left a comment

Choose a reason for hiding this comment

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

Thanks a lot for this PR, it pushes things on the right direction.

I just ping'd @MarkMcCaskey so we can see how to handle properly the imports, but other than that, it looks great... good work!

Comment on lines 54 to 65
if requested.minimum > self.max_memory {
return Err(MemoryError::Generic(
"Minimum of requested memory exceeds the allowed memory limit".to_string(),
));
}

if let Some(max) = requested.maximum {
if max > self.max_memory {
return Err(MemoryError::Generic(
"Maximum of requested memory exceeds the allowed memory limit".to_string(),
));
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

One thing, if we expect users to be able to handle these errors programmatically, we should use semantic error values rather than a String via MemoryError::Generic if this error is something fatal then a String is fine

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, I just realized that this is an example 😆 , this is neat!

The same still holds though, we may want to add error values for these if we want users to be able to handle them better. We can adjust this this after shipping this example though, so let's ship it as-is for now and then follow up with possibly adding error values that are easier to match on.

Copy link
Contributor Author

@webmaster128 webmaster128 Oct 17, 2020

Choose a reason for hiding this comment

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

I'm happy either way. I could create the error types, but then again the whole concept of memory limits is a customization and the errors also belong in the customization. So maybe the question is whether or not the error type must be customizable in Result<Arc<dyn MemoryTrait>, MemoryError>.

@webmaster128 webmaster128 force-pushed the tunables_limit_memory branch from b13953b to 0773e52 Compare October 17, 2020 08:57
bors bot added a commit that referenced this pull request Oct 27, 2020
1752: Add more examples for the Rust API r=syrusakbary a=jubianchi

# Description

The goal is to cover most of the Rust API with examples (and thus tests).

Some other PRs already exist for that purpose:
* #1730
* #1687 

# Review

- [ ] Add a short description of the the change to the CHANGELOG.md file


Co-authored-by: jubianchi <[email protected]>
@webmaster128
Copy link
Contributor Author

I can update this PR at any time. Just waiting for some clear guidance on the Wasmer exports, especially how to deal with vm and the collisions. This I cannot decide really.

@MarkMcCaskey
Copy link
Contributor

@webmaster128 thanks for the ping! I think for now let's go with exporting a sub-module like vm from wasmer, so you can use use wasmer::vm::Memory as _; to get the trait in scope or use it directly as vm::Memory.

I personally think it's probably also a good idea to rename the Memory trait in vm to something unambiguous as well, but we can do that later -- the wasmer sub-module should be a reasonable way to unblock this!

@webmaster128 webmaster128 force-pushed the tunables_limit_memory branch from 0773e52 to 1337d73 Compare October 27, 2020 23:40
@webmaster128
Copy link
Contributor Author

Alright, thanks. I now created wasmer::vm, such that I could remove wasmer-vm from the root Cargo.toml again. This is also updated to the changes in the Tunables trait.

The example got a little fancier as the base Tunables is now generic, such that you can use LimitingTunables on top of any Tunables implementation.

Copy link
Contributor

@MarkMcCaskey MarkMcCaskey left a comment

Choose a reason for hiding this comment

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

Looks good to me! I'll ping Syrus too

@@ -81,7 +81,17 @@ pub use wasmer_types::{
Atomically, Bytes, GlobalInit, LocalFunctionIndex, MemoryView, Pages, ValueType,
WASM_MAX_PAGES, WASM_MIN_PAGES, WASM_PAGE_SIZE,
};

// TODO: should those be moved into wasmer::vm as well?
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps, but they should probably stay at the top level too!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

okay, feel free to just kick out the comment when you are happy with the setup

@webmaster128
Copy link
Contributor Author

Hope you don't mind I linked this to close #1588. Let me know if I am missing something.

@syrusakbary
Copy link
Member

Looks great. Merging.

bors r+

@bors
Copy link
Contributor

bors bot commented Oct 28, 2020

@bors bors bot merged commit eec90e7 into wasmerio:master Oct 28, 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.

How to use new Tunables API
3 participants