Skip to content

Commit

Permalink
Add parallel execution example
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark McCaskey committed Sep 26, 2019
1 parent c52c44a commit 0ed6103
Show file tree
Hide file tree
Showing 10 changed files with 285 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Blocks of changes will separated by version increments.

## **[Unreleased]**

- [#834](https://github.com/wasmerio/wasmer/pull/834) Fix panic when unwraping `wasmer` arguments
- [#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`.
Expand Down
24 changes: 24 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ members = [
"lib/emscripten-tests",
"lib/middleware-common-tests",
"examples/plugin-for-example",
"examples/parallel",
"examples/parallel-guest",
]

[build-dependencies]
Expand Down
Binary file added examples/parallel-guest.wasm
Binary file not shown.
11 changes: 11 additions & 0 deletions examples/parallel-guest/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "parallel-guest"
version = "0.1.0"
authors = ["The Wasmer Engineering Team <[email protected]>"]
license = "MIT"
edition = "2018"
publish = false

[dependencies]
md5 = "0.6"
lazy_static = "1"
82 changes: 82 additions & 0 deletions examples/parallel-guest/src/main.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 14 additions & 0 deletions examples/parallel/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "parallel"
version = "0.1.0"
authors = ["The Wasmer Engineering Team <[email protected]>"]
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 changes: 5 additions & 0 deletions examples/parallel/README.md
Original file line number Diff line number Diff line change
@@ -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 changes: 137 additions & 0 deletions examples/parallel/src/main.rs
Original file line number Diff line number Diff line change
@@ -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!");
}
}
9 changes: 9 additions & 0 deletions examples/parallel/wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Serial:
a; b; c; d; e; f; g; h; i; j; k; l; m; n; o; p; q; r; s; t; u; v; w; x; y; z; A; B; C; D; E; F; G; H; I; J; K; L; M; N; O; P; Q; R; S; T; U; V; W; X; Y; Z; 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; ab; bb; cb; db; eb; fb; gb; hb; ib; jb; kb; lb; mb; nb; ob; pb; qb; rb; sb; tb; ub; vb; wb; xb; yb; zb; Ab; Bb; Cb; Db; Eb; Fb; Gb; Hb; Ib; Jb; Kb; Lb; Mb; Nb; Ob; Pb; Qb; Rb; Sb; Tb; Ub; Vb; Wb; Xb; Yb; Zb; 0b; 1b; 2b; 3b; 4b; 5b; 6b; 7b; 8b; 9b; ac; bc; cc; dc; ec; fc; gc; hc; ic; jc; kc; lc; mc; nc; oc; pc; qc; rc; sc; tc; uc; vc; wc; xc; yc; zc; Ac; Bc; Cc; Dc; Ec; Fc; Gc; Hc; Ic; Jc; Kc; Lc; Mc; Nc; Oc; Pc; Qc; Rc; Sc; Tc; Uc; Vc; Wc; Xc; Yc; Zc; 0c; 1c; 2c; 3c; 4c; 5c; 6c; 7c; 8c; 9c; ad; bd; cd; dd; ed; fd; gd; hd; id; jd; kd; ld; md; nd; od; pd; qd; rd; sd; td; ud; vd; wd; xd; yd; zd; Ad; Bd; Cd; Dd; Ed; Fd; Gd; Hd; Id; Jd; Kd; Ld; Md; Nd; Od; Pd; Qd; Rd; Sd; Td; Ud; Vd; Wd; Xd; Yd; Zd; 0d; 1d; 2d; 3d; 4d; 5d; 6d; 7d; 8d; 9d; ae; be; ce; de; ee; fe; ge; he; ie; je; ke; le; me; ne; oe; pe; qe; re; se; te; ue; ve; we; xe; ye; ze; Ae; Be; Ce; De; Ee; Fe; Ge; He; Ie; Je; Ke; Le; Me; Ne; Oe; Pe; Qe; Re; Se; Te; Ue; Ve; We; Xe; Ye; Ze; 0e; 1e; 2e; 3e; 4e; 5e; 6e; 7e; 8e; 9e; af; bf; cf; df; ef; ff; gf; hf; if; jf; kf; lf; mf; nf; of; pf; qf; rf; sf; tf; uf; vf; wf; xf; yf; zf; Af; Bf; Cf; Df; Ef; Ff; Gf; Hf; If; Jf; Kf; Lf; Mf; Nf; Of; Pf; Qf; Rf; Sf; Tf; Uf; Vf; Wf; Xf; Yf; Zf; 0f; 1f; 2f; 3f; 4f; 5f; 6f; 7f; 8f; 9f; ag; bg; cg; dg; eg; fg; gg; hg; ig; jg; kg; lg; mg; ng; og; pg; qg; rg; sg; tg; ug; vg; wg; xg; yg; zg; Ag; Bg; Cg; Dg; Eg; Fg; Gg; Hg; Ig; Jg; Kg; Lg; Mg; Ng; Og; Pg; Qg; Rg; Sg; Tg; Ug; Vg; Wg; Xg; Yg; Zg; 0g; 1g; 2g; 3g; 4g; 5g; 6g; 7g; 8g; 9g; ah; bh; ch; dh; eh; fh; gh; hh; ih; jh; kh; lh; mh; nh; oh; ph; qh; rh; sh; th; uh; vh; wh; xh; yh; zh; Ah; Bh; Ch; Dh; Eh; Fh; Gh; Hh; Ih; Jh; Kh; Lh; Mh; Nh; Oh; Ph; Qh; Rh; Sh; Th; Uh; Vh; Wh; Xh; Yh; Zh; 0h; 1h; 2h; 3h; 4h; 5h; 6h; 7h; 8h; 9h; ai; bi; ci; di; ei; fi; gi; hi; ii; ji; ki; li; mi; ni; oi; pi; qi; ri; si; ti; ui; vi; wi; xi; yi; zi; Ai; Bi; Ci; Di; Ei; Fi; Gi; Hi; Ii; Ji; Ki; Li; Mi; Ni; Oi; Pi; Qi; Ri; Si; Ti; Ui; Vi; Wi; Xi; Yi; Zi; 0i; 1i; 2i; 3i; 4i; 5i; 6i; 7i; 8i; 9i; aj; bj; cj; dj; ej; fj; gj; hj; ij; jj; kj; lj; mj; nj; oj; pj; qj; rj; sj; tj; uj; vj; wj; xj; yj; zj; Aj; Bj; Cj; Dj; Ej; Fj; Gj; Hj; Ij; Jj; Kj; Lj; Mj; Nj; Oj; Pj; Qj; Rj; Sj; Tj; Uj; Vj; Wj; Xj; Yj; Zj; 0j; 1j; 2j; 3j; 4j; 5j; 6j; 7j; 8j; 9j; ak; bk; ck; dk; ek; fk; gk; hk; ik; jk; kk; lk; mk; nk; ok; pk; qk; rk; sk; tk; uk; vk; wk; xk; yk; zk; Ak; Bk; Ck; Dk; Ek; Fk; Gk; Hk; Ik; Jk; Kk; Lk; Mk; Nk; Ok; Pk; Qk; Rk; Sk; Tk; Uk; Vk; Wk; Xk; Yk; Zk; 0k; 1k; 2k; 3k; 4k; 5k; 6k; 7k; 8k; 9k; al; bl; cl; dl; el; fl; gl; hl; il; jl; kl; ll; ml; nl; ol; pl; ql; rl; sl; tl; ul; vl; wl; xl; yl; zl; Al; Bl; Cl; Dl; El; Fl; Gl; Hl; Il; Jl; Kl; Ll; Ml; Nl; Ol; Pl; Ql; Rl; Sl; Tl; Ul; Vl; Wl; Xl; Yl; Zl; 0l; 1l; 2l; 3l; 4l; 5l; 6l; 7l; 8l; 9l; am; bm; cm; dm; em; fm; gm; hm; im; jm; km; lm; mm; nm; om; pm; qm; rm; sm; tm; um; vm; wm; xm; ym; zm; Am; Bm; Cm; Dm; Em; Fm; Gm; Hm; Im; Jm; Km; Lm; Mm; Nm; Om; Pm; Qm; Rm; Sm; Tm; Um; Vm; Wm; Xm; Ym; Zm; 0m; 1m; 2m; 3m; 4m; 5m; 6m; 7m; 8m; 9m; an; bn; cn; dn; en; fn; gn; hn; in; jn; kn; ln; mn; nn; on; pn; qn; rn; sn; tn; un; vn; wn; xn; yn; zn; An; Bn; Cn; Dn; En; Fn; Gn; Hn; In; Jn; Kn; Ln; Mn; Nn; On; Pn; Qn; Rn; Sn; Tn; Un; Vn; Wn; Xn; Yn; Zn; 0n; 1n; 2n; 3n; 4n; 5n; 6n; 7n; 8n; 9n; ao; bo; co; do; eo; fo; go; ho; io; jo; ko; lo; mo; no; oo; po; qo; ro; so; to; uo; vo; wo; xo; yo; zo; Ao; Bo; Co; Do; Eo; Fo; Go; Ho; Io; Jo; Ko; Lo; Mo; No; Oo; Po; Qo; Ro; So; To; Uo; Vo; Wo; Xo; Yo; Zo; 0o; 1o; 2o; 3o; 4o; 5o; 6o; 7o; 8o; 9o; ap; bp; cp; dp; ep; fp; gp; hp; ip; jp; kp; lp; mp; np; op; pp; qp; rp; sp; tp; up; vp; wp; xp; yp; zp; Ap; Bp; Cp; Dp; Ep; Fp; Gp; Hp; Ip; Jp; Kp; Lp; Mp; Np; Op; Pp; Qp; Rp; Sp; Tp; Up; Vp; Wp; Xp; Yp; Zp; 0p; 1p; 2p; 3p; 4p; 5p; 6p; 7p; 8p; 9p; aq; bq; cq; dq; eq; fq; gq; hq; iq; jq; kq; lq; mq; nq; oq; pq; qq; rq; sq; tq; uq; vq; wq; xq; yq; zq; Aq; Bq; Cq; Dq; Eq; Fq;
0cc175b9c0f1b6a831c399e269772661
0cc175b9c0f1b6a831c399e269772661
a
0cc175b9c0f1b6a831c399e269772661
RESULT: 4296081456
.
Password cracked: "a"

0 comments on commit 0ed6103

Please sign in to comment.