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

Metering. #450

Merged
merged 35 commits into from
Jun 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
6aa87a0
Add the `internals` field and necessary structures for metering.
losfair May 16, 2019
7e79dd2
Metering middleware.
losfair May 16, 2019
e7297b9
Update singlepass backend to support metering.
losfair May 16, 2019
14fcd78
Update bin/wasmer and run cargo fmt.
losfair May 16, 2019
b830f10
Update metering data on return
losfair May 16, 2019
8e0d71b
Fix missing `internals` in test.
losfair May 16, 2019
6aec1c4
Use `INTERNALS_SIZE`
losfair May 16, 2019
cf58305
Dynamically allocate internal fields.
losfair May 23, 2019
dcf52ef
Cargo fmt
losfair May 23, 2019
9919dd7
Merge remote-tracking branch 'origin/master' into feature/metering
losfair May 23, 2019
68a8800
Temporarily use the original zbox.
losfair May 23, 2019
fd86753
Merge remote-tracking branch 'origin/master' into feature/metering
losfair May 29, 2019
b834b4f
Metering for LLVM.
losfair May 31, 2019
8019505
Merge remote-tracking branch 'origin/feature/clif-cgapi' into feature…
losfair May 31, 2019
c1e817b
Add missing relaxed moves.
losfair May 31, 2019
f029ea6
Merge branch 'master' into feature/metering
bjfish Jun 2, 2019
995ecef
Cargo fmt
bjfish Jun 2, 2019
e533a8a
Add tests for metering, add option to compiler config
bjfish Jun 2, 2019
c020c39
Move get/set points used to middleware
bjfish Jun 2, 2019
f9c8f41
Remove points_limit and update tests
bjfish Jun 2, 2019
8fdc4f9
Start documenting Metering
bjfish Jun 2, 2019
0c3109f
Update Makefile and test configuration
bjfish Jun 2, 2019
605c0dc
Fix indentation in Makefile
bjfish Jun 2, 2019
151af82
Remove debugging println
bjfish Jun 2, 2019
66f9049
Reset LLVM related code to master
bjfish Jun 3, 2019
69944c1
Fix ctx layout in LLVM.
losfair Jun 4, 2019
0867208
Implement {get,set}_points_used.
losfair Jun 4, 2019
f2d8aad
Support checking the execution limit exceeded error.
losfair Jun 5, 2019
f5243af
Cargo fmt
losfair Jun 5, 2019
f832c8d
Try to fix unused import error
bjfish Jun 5, 2019
27eacf0
Add metering benchmark
bjfish Jun 6, 2019
c6cd49a
Support getting/setting metering points and internal fields with a Ctx.
losfair Jun 6, 2019
418764a
Add get/set gas used for benchmark
bjfish Jun 7, 2019
e87d507
Add black_box to benchmarking
bjfish Jun 7, 2019
f6ecfa4
Merge branch 'master' into feature/metering
bjfish Jun 7, 2019
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
5 changes: 5 additions & 0 deletions Cargo.lock

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

5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,21 @@ do-install:

test:
# We use one thread so the emscripten stdouts doesn't collide
cargo test --all --exclude wasmer-runtime-c-api --exclude wasmer-emscripten --exclude wasmer-spectests --exclude wasmer-singlepass-backend --exclude wasmer-wasi -- $(runargs)
cargo test --all --exclude wasmer-runtime-c-api --exclude wasmer-emscripten --exclude wasmer-spectests --exclude wasmer-singlepass-backend --exclude wasmer-wasi --exclude wasmer-middleware-common -- $(runargs)
# cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs)
cargo test --manifest-path lib/spectests/Cargo.toml --features clif
cargo test --manifest-path lib/middleware-common/Cargo.toml --features clif
@if [ ! -z "${CIRCLE_JOB}" ]; then rm -f /home/circleci/project/target/debug/deps/libcranelift_wasm* && rm -f /Users/distiller/project/target/debug/deps/libcranelift_wasm*; fi;
cargo test --manifest-path lib/spectests/Cargo.toml --features llvm
cargo test --manifest-path lib/runtime/Cargo.toml --features llvm
cargo test --manifest-path lib/middleware-common/Cargo.toml --features llvm
cargo build -p wasmer-runtime-c-api
cargo test -p wasmer-runtime-c-api -- --nocapture

test-singlepass:
cargo test --manifest-path lib/spectests/Cargo.toml --features singlepass
cargo test --manifest-path lib/runtime/Cargo.toml --features singlepass
cargo test --manifest-path lib/middleware-common/Cargo.toml --features singlepass

test-emscripten-llvm:
cargo test --manifest-path lib/emscripten/Cargo.toml --features llvm -- --test-threads=1 $(runargs)
Expand Down
1 change: 1 addition & 0 deletions lib/clif-backend/src/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,7 @@ impl FunctionCodeGenerator<CodegenError> for CraneliftFunctionCodeGenerator {
fn feed_event(&mut self, event: Event, _module_info: &ModuleInfo) -> Result<(), CodegenError> {
let op = match event {
Event::Wasm(x) => x,
Event::WasmOwned(ref x) => x,
Event::Internal(_x) => {
return Ok(());
}
Expand Down
1 change: 1 addition & 0 deletions lib/llvm-backend/src/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
Event::Internal(_x) => {
return Ok(());
}
Event::WasmOwned(ref x) => x,
};

let mut state = &mut self.state;
Expand Down
4 changes: 4 additions & 0 deletions lib/llvm-backend/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ impl Intrinsics {
let stack_lower_bound_ty = i8_ty;
let memory_base_ty = i8_ty;
let memory_bound_ty = void_ty;
let internals_ty = i64_ty;
let local_function_ty = i8_ptr_ty;

let anyfunc_ty = context.struct_type(
Expand Down Expand Up @@ -218,6 +219,9 @@ impl Intrinsics {
memory_bound_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
internals_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
local_function_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
Expand Down
18 changes: 17 additions & 1 deletion lib/middleware-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,20 @@ authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
edition = "2018"

[dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" }
wasmer-runtime-core = { path = "../runtime-core" }
wasmer-clif-backend = { path = "../clif-backend", version = "0.4.2" }
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.4.2", optional = true }
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.4.2", optional = true }

[dev-dependencies]
wabt = "0.7.4"
criterion = "0.2"

[features]
clif = []
llvm = ["wasmer-llvm-backend"]
singlepass = ["wasmer-singlepass-backend"]

[[bench]]
name = "metering_benchmark"
harness = false
230 changes: 230 additions & 0 deletions lib/middleware-common/benches/metering_benchmark.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
#[macro_use]
extern crate criterion;

use criterion::black_box;
use criterion::{Benchmark, Criterion};

use wabt::wat2wasm;

use wasmer_middleware_common::metering::Metering;
use wasmer_runtime_core::vm::Ctx;
use wasmer_runtime_core::{backend::Compiler, compile_with, imports, Func};

//export function add_to(x: i32, y: i32): i32 {
// for(var i = 0; i < x; i++){
// if(i % 1 == 0){
// y += i;
// } else {
// y *= i
// }
// }
// return y;
//}
static WAT: &'static str = r#"
(module
(type $t0 (func (param i32 i32) (result i32)))
(type $t1 (func))
(func $add_to (export "add_to") (type $t0) (param $p0 i32) (param $p1 i32) (result i32)
(local $l0 i32)
block $B0
i32.const 0
set_local $l0
loop $L1
get_local $l0
get_local $p0
i32.lt_s
i32.eqz
br_if $B0
get_local $l0
i32.const 1
i32.rem_s
i32.const 0
i32.eq
if $I2
get_local $p1
get_local $l0
i32.add
set_local $p1
else
get_local $p1
get_local $l0
i32.mul
set_local $p1
end
get_local $l0
i32.const 1
i32.add
set_local $l0
br $L1
unreachable
end
unreachable
end
get_local $p1)
(func $f1 (type $t1))
(table $table (export "table") 1 anyfunc)
(memory $memory (export "memory") 0)
(global $g0 i32 (i32.const 8))
(elem (i32.const 0) $f1))
"#;

static WAT_GAS: &'static str = r#"
(module
(type $t0 (func (param i32 i32) (result i32)))
(type $t1 (func))
(type $t2 (func (param i32)))
(import "env" "gas" (func $env.gas (type $t2)))
(func $add_to (type $t0) (param $p0 i32) (param $p1 i32) (result i32)
(local $l0 i32)
i32.const 3
call $env.gas
block $B0
i32.const 5
call $env.gas
i32.const 0
set_local $l0
loop $L1
i32.const 18
call $env.gas
get_local $l0
get_local $p0
i32.lt_s
i32.eqz
br_if $B0
get_local $l0
i32.const 1
i32.rem_s
i32.const 0
i32.eq
if $I2
i32.const 5
call $env.gas
get_local $p1
get_local $l0
i32.add
set_local $p1
else
i32.const 5
call $env.gas
get_local $p1
get_local $l0
i32.mul
set_local $p1
end
get_local $l0
i32.const 1
i32.add
set_local $l0
br $L1
unreachable
end
unreachable
end
get_local $p1)
(func $f2 (type $t1)
i32.const 1
call $env.gas)
(table $table 1 anyfunc)
(memory $memory 0)
(global $g0 i32 (i32.const 8))
(export "memory" (memory 0))
(export "table" (table 0))
(export "add_to" (func $add_to))
(elem (i32.const 0) $f2))
"#;

#[cfg(feature = "llvm")]
fn get_compiler(limit: u64, metering: bool) -> impl Compiler {
use wasmer_llvm_backend::code::LLVMModuleCodeGenerator;
use wasmer_runtime_core::codegen::{MiddlewareChain, StreamingCompiler};
let c: StreamingCompiler<LLVMModuleCodeGenerator, _, _, _, _> =
StreamingCompiler::new(move || {
let mut chain = MiddlewareChain::new();
if metering {
chain.push(Metering::new(limit));
}
chain
});

c
}

#[cfg(feature = "singlepass")]
fn get_compiler(limit: u64, metering: bool) -> impl Compiler {
use wasmer_runtime_core::codegen::{MiddlewareChain, StreamingCompiler};
use wasmer_singlepass_backend::ModuleCodeGenerator as SinglePassMCG;
let c: StreamingCompiler<SinglePassMCG, _, _, _, _> = StreamingCompiler::new(move || {
let mut chain = MiddlewareChain::new();
if metering {
chain.push(Metering::new(limit));
}
chain
});
c
}

#[cfg(not(any(feature = "llvm", feature = "clif", feature = "singlepass")))]
fn get_compiler(_limit: u64, metering: bool) -> impl Compiler {
panic!("compiler not specified, activate a compiler via features");
use wasmer_clif_backend::CraneliftCompiler;
CraneliftCompiler::new()
}

#[cfg(feature = "clif")]
fn get_compiler(_limit: u64, metering: bool) -> impl Compiler {
panic!("cranelift does not implement metering");
use wasmer_clif_backend::CraneliftCompiler;
CraneliftCompiler::new()
}

fn gas(ctx: &mut Ctx, gas_amount: u32) {
use wasmer_middleware_common::metering;
let used = metering::get_points_used_ctx(ctx);
metering::set_points_used_ctx(ctx, used + u64::from(gas_amount));
()
}

fn bench_metering(c: &mut Criterion) {
use wasmer_middleware_common::metering;

c.bench(
"Meter",
Benchmark::new("No Metering", |b| {
let compiler = get_compiler(0, false);
let wasm_binary = wat2wasm(WAT).unwrap();
let module = compile_with(&wasm_binary, &compiler).unwrap();
let import_object = imports! {};
let mut instance = module.instantiate(&import_object).unwrap();
let add_to: Func<(i32, i32), i32> = instance.func("add_to").unwrap();
b.iter(|| black_box(add_to.call(100, 4)))
})
.with_function("Gas Metering", |b| {
let compiler = get_compiler(0, false);
let gas_wasm_binary = wat2wasm(WAT_GAS).unwrap();
let gas_module = compile_with(&gas_wasm_binary, &compiler).unwrap();
let gas_import_object = imports! {
"env" => {
"gas" => Func::new(gas),
},
};
let mut gas_instance = gas_module.instantiate(&gas_import_object).unwrap();
let gas_add_to: Func<(i32, i32), i32> = gas_instance.func("add_to").unwrap();
b.iter(|| black_box(gas_add_to.call(100, 4)))
})
.with_function("Built-in Metering", |b| {
let metering_compiler = get_compiler(std::u64::MAX, true);
let wasm_binary = wat2wasm(WAT).unwrap();
let metering_module = compile_with(&wasm_binary, &metering_compiler).unwrap();
let metering_import_object = imports! {};
let mut metering_instance = metering_module
.instantiate(&metering_import_object)
.unwrap();
metering::set_points_used(&mut metering_instance, 0u64);
let metering_add_to: Func<(i32, i32), i32> = metering_instance.func("add_to").unwrap();
b.iter(|| black_box(metering_add_to.call(100, 4)))
}),
);
}

criterion_group!(benches, bench_metering);
criterion_main!(benches);
1 change: 1 addition & 0 deletions lib/middleware-common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)]

pub mod call_trace;
pub mod metering;
Loading