mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-04 18:10:18 +00:00
Add parallel execution example
This commit is contained in:
parent
287b42579c
commit
1083e7cd2a
@ -6,9 +6,11 @@ Blocks of changes will separated by version increments.
|
||||
|
||||
## **[Unreleased]**
|
||||
|
||||
- [#835](https://github.com/wasmerio/wasmer/pull/836) Update Cranelift fork version to `0.44.0`
|
||||
- [#836](https://github.com/wasmerio/wasmer/pull/836) Update Cranelift fork version to `0.44.0`
|
||||
- [#839](https://github.com/wasmerio/wasmer/pull/839) Change supported version to stable Rust 1.37+
|
||||
- [#834](https://github.com/wasmerio/wasmer/pull/834) Fix panic when unwraping `wasmer` arguments
|
||||
- [#835](https://github.com/wasmerio/wasmer/pull/835) Add parallel execution example (independent instances created from the same `ImportObject` and `Module` run with rayon)
|
||||
- [#834](https://github.com/wasmerio/wasmer/pull/834) Fix panic when parsing numerical arguments for no-ABI targets run with the wasmer binary
|
||||
- [#833](https://github.com/wasmerio/wasmer/pull/833) Add doc example of using ImportObject's new `maybe_with_namespace` method
|
||||
- [#832](https://github.com/wasmerio/wasmer/pull/832) Delete unused runtime ABI
|
||||
- [#809](https://github.com/wasmerio/wasmer/pull/809) Fix bugs leading to panics in `LocalBacking`.
|
||||
|
24
Cargo.lock
generated
24
Cargo.lock
generated
@ -734,6 +734,11 @@ dependencies = [
|
||||
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "md5"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.2.1"
|
||||
@ -828,6 +833,24 @@ dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parallel"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime 0.7.0",
|
||||
"wasmer-runtime-core 0.7.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parallel-guest"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.9.0"
|
||||
@ -1884,6 +1907,7 @@ dependencies = [
|
||||
"checksum llvm-sys 80.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2110cd4daf9cd8e39dd3b933b1a2a2ac7315e91f7c92b3a20beab526c63b5978"
|
||||
"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc"
|
||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||
"checksum md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e6bcd6433cff03a4bfc3d9834d504467db1f1cf6d0ea765d37d330249ed629d"
|
||||
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
|
||||
"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
|
||||
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
|
||||
|
@ -57,6 +57,8 @@ members = [
|
||||
"lib/emscripten-tests",
|
||||
"lib/middleware-common-tests",
|
||||
"examples/plugin-for-example",
|
||||
"examples/parallel",
|
||||
"examples/parallel-guest",
|
||||
]
|
||||
|
||||
[build-dependencies]
|
||||
|
BIN
examples/parallel-guest.wasm
Executable file
BIN
examples/parallel-guest.wasm
Executable file
Binary file not shown.
11
examples/parallel-guest/Cargo.toml
Normal file
11
examples/parallel-guest/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "parallel-guest"
|
||||
version = "0.1.0"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
license = "MIT"
|
||||
edition = "2018"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
md5 = "0.6"
|
||||
lazy_static = "1"
|
82
examples/parallel-guest/src/main.rs
Normal file
82
examples/parallel-guest/src/main.rs
Normal file
@ -0,0 +1,82 @@
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
extern "C" {
|
||||
fn get_hashed_password(ptr: u32, len: u32) -> u32;
|
||||
fn print_char(c: u32);
|
||||
}
|
||||
|
||||
fn print_str(s: &str) {
|
||||
for c in s.chars() {
|
||||
unsafe { print_char(c as u32) };
|
||||
}
|
||||
unsafe { print_char(b'\n' as u32) };
|
||||
}
|
||||
|
||||
fn load_hashed_password() -> Option<String> {
|
||||
let mut buffer = String::with_capacity(32);
|
||||
for _ in 0..32 {
|
||||
buffer.push(0 as char);
|
||||
}
|
||||
let result =
|
||||
unsafe { get_hashed_password(buffer.as_mut_ptr() as u32, buffer.capacity() as u32) };
|
||||
|
||||
if result == 0 {
|
||||
Some(buffer)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref HASHED_PASSWORD: String = load_hashed_password().unwrap();
|
||||
}
|
||||
|
||||
static PASSWORD_CHARS: &'static [u8] = b"abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
// for simplicty we define a scheme for mapping numbers onto passwords
|
||||
fn num_to_password(mut num: u64) -> String {
|
||||
let mut extra_zero = num == 0;
|
||||
let mut out = String::new();
|
||||
while num > 0 {
|
||||
out.push(PASSWORD_CHARS[num as usize % PASSWORD_CHARS.len()] as char);
|
||||
extra_zero = extra_zero || num == PASSWORD_CHARS.len() as u64;
|
||||
num /= PASSWORD_CHARS.len() as u64;
|
||||
}
|
||||
|
||||
if extra_zero {
|
||||
out.push(PASSWORD_CHARS[0] as char);
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct RetStr {
|
||||
ptr: u32,
|
||||
len: u32,
|
||||
}
|
||||
|
||||
// returns a (pointer, len) to the password or null
|
||||
#[no_mangle]
|
||||
fn check_password(from: u64, to: u64) -> u64 {
|
||||
for i in from..to {
|
||||
let password = num_to_password(i);
|
||||
let digest = md5::compute(&password);
|
||||
|
||||
let hash_as_str = format!("{:x}", digest);
|
||||
if hash_as_str == *HASHED_PASSWORD {
|
||||
let ret = RetStr {
|
||||
ptr: password.as_ptr() as usize as u32,
|
||||
len: password.len() as u32,
|
||||
};
|
||||
// leak the data so ending the function doesn't corrupt it, if we cared the host could free it after
|
||||
std::mem::forget(password);
|
||||
return unsafe { std::mem::transmute(ret) };
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn main() {}
|
14
examples/parallel/Cargo.toml
Normal file
14
examples/parallel/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "parallel"
|
||||
version = "0.1.0"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
edition = "2018"
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
publish = false
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
rayon = "1.2"
|
||||
time = "0.1"
|
||||
wasmer-runtime = { path = "../../lib/runtime" }
|
||||
wasmer-runtime-core = { path = "../../lib/runtime-core" }
|
5
examples/parallel/README.md
Normal file
5
examples/parallel/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Parallel Wasmer example
|
||||
|
||||
This example shows executing independent code from multiple threads on an "embarassingly parallel" problem
|
||||
|
||||
This is a toy example of cracking md5 hashes. This is not a benchmark. This example is not optimized, it will compare poorly to an implementation that is.
|
137
examples/parallel/src/main.rs
Normal file
137
examples/parallel/src/main.rs
Normal file
@ -0,0 +1,137 @@
|
||||
use rayon::prelude::*;
|
||||
use wasmer_runtime::{compile_with, compiler_for_backend, func, imports, instantiate, Backend};
|
||||
use wasmer_runtime_core::{
|
||||
memory::ptr::{Array, WasmPtr},
|
||||
vm::Ctx,
|
||||
};
|
||||
|
||||
static PLUGIN_LOCATION: &'static str = "../parallel-guest.wasm";
|
||||
|
||||
fn get_hashed_password(ctx: &mut Ctx, ptr: WasmPtr<u8, Array>, len: u32) -> u32 {
|
||||
// "hard" password - 7 characters
|
||||
//let password = b"2ab96390c7dbe3439de74d0c9b0b1767";
|
||||
// "easy" password - 5 characters
|
||||
let password = b"ab56b4d92b40713acc5af89985d4b786";
|
||||
let memory = ctx.memory(0);
|
||||
if let Some(writer) = ptr.deref(memory, 0, len) {
|
||||
for (i, byte) in password.iter().enumerate() {
|
||||
writer[i].set(*byte)
|
||||
}
|
||||
|
||||
0
|
||||
} else {
|
||||
u32::max_value()
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct RetStr {
|
||||
ptr: u32,
|
||||
len: u32,
|
||||
}
|
||||
|
||||
fn print_char(_cxt: &mut Ctx, c: u32) {
|
||||
print!("{}", c as u8 as char);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let wasm_bytes = std::fs::read(PLUGIN_LOCATION).expect(&format!(
|
||||
"Could not read in WASM plugin at {}",
|
||||
PLUGIN_LOCATION
|
||||
));
|
||||
|
||||
let imports = imports! {
|
||||
"env" => {
|
||||
"get_hashed_password" => func!(get_hashed_password),
|
||||
"print_char" => func!(print_char),
|
||||
},
|
||||
};
|
||||
let compiler = compiler_for_backend(Backend::default()).unwrap();
|
||||
let module = compile_with(&wasm_bytes[..], compiler.as_ref()).unwrap();
|
||||
|
||||
println!("Parallel");
|
||||
let start_ts = time::SteadyTime::now();
|
||||
for outer in 0..1000u64 {
|
||||
let start = outer * 1000;
|
||||
let end = start + 1000;
|
||||
let out = (start..=end)
|
||||
.into_par_iter()
|
||||
.filter_map(|i| {
|
||||
let instance = module
|
||||
.clone()
|
||||
.instantiate(&imports)
|
||||
.expect("failed to instantiate wasm module");
|
||||
let check_password = instance.func::<(u64, u64), u64>("check_password").unwrap();
|
||||
let j = i * 10000;
|
||||
let result = check_password.call(j, j + 10000).unwrap();
|
||||
print!(".");
|
||||
use std::io::Write;
|
||||
std::io::stdout().flush().unwrap();
|
||||
if result != 0 {
|
||||
let res: RetStr = unsafe { std::mem::transmute(result) };
|
||||
|
||||
let ctx = instance.context();
|
||||
let memory = ctx.memory(0);
|
||||
let wasm_ptr: WasmPtr<u8, Array> = WasmPtr::new(res.ptr);
|
||||
let password_str = wasm_ptr
|
||||
.get_utf8_string(memory, res.len)
|
||||
.unwrap()
|
||||
.to_string();
|
||||
Some(password_str)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.find_first(|_: &String| true);
|
||||
if out.is_some() {
|
||||
let end_ts = time::SteadyTime::now();
|
||||
let delta = end_ts - start_ts;
|
||||
println!(
|
||||
"Password cracked: \"{}\" in {}.{:03}",
|
||||
out.unwrap(),
|
||||
delta.num_seconds(),
|
||||
(delta.num_milliseconds() % 1000),
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
println!("Serial:");
|
||||
let start_ts = time::SteadyTime::now();
|
||||
let instance =
|
||||
instantiate(&wasm_bytes[..], &imports).expect("failed to instantiate wasm module");
|
||||
|
||||
let check_password = instance.func::<(u64, u64), u64>("check_password").unwrap();
|
||||
|
||||
let mut out: Option<RetStr> = None;
|
||||
for i in (0..=u64::max_value()).step_by(10000) {
|
||||
let result = check_password.call(i, i + 10000).unwrap();
|
||||
print!(".");
|
||||
use std::io::Write;
|
||||
std::io::stdout().flush().unwrap();
|
||||
if result != 0 {
|
||||
out = Some(unsafe { std::mem::transmute(result) });
|
||||
break;
|
||||
}
|
||||
}
|
||||
println!("");
|
||||
|
||||
if let Some(res) = out {
|
||||
let ctx = instance.context();
|
||||
let memory = ctx.memory(0);
|
||||
let wasm_ptr: WasmPtr<u8, Array> = WasmPtr::new(res.ptr);
|
||||
|
||||
let password_str = wasm_ptr.get_utf8_string(memory, res.len).unwrap();
|
||||
|
||||
let end_ts = time::SteadyTime::now();
|
||||
let delta = end_ts - start_ts;
|
||||
println!(
|
||||
"Password cracked: \"{}\" in {}.{:03}",
|
||||
password_str,
|
||||
delta.num_seconds(),
|
||||
(delta.num_milliseconds() % 1000),
|
||||
);
|
||||
} else {
|
||||
println!("Password not found!");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user