mirror of
https://github.com/pezkuwichain/wasm-instrument.git
synced 2026-04-28 02:47:58 +00:00
Add new gas metering method: mutable global + local gas function (#34)
* fix misprints in doc comments * added global gas tracker variable and local gas fn * all exported functions of the module to accept a new param and to set the gas_left global to its value at their very start * make module support both gas metering methods * tests fixed for the old metering method * better naming * MutableGlobal metering method implemented, tests for the old method pass * gas_metering::tests updated and pass * all tests udpdated and pass * emacs backup files to .gitignore * docs updated * clippy fix * iff = if and only if * more clippy * docs misprints fixes * refactored to have Backend trait and two implementations in separate sub-modules * docs updated * fixed old benches (updating them is coming next) * added bench for an instrumented wasm-coremark * updated benches: added them for both gas_metering instrumentations * benches contest first ver * added debug prints to the bench * refactored to better fit frontend-backend pattern * docs update * updated benches * design updated on feedback * re-structured sub-modules re-structured sub-modules & updated docs * docs improved * addressed latest feedback comments * re-writed the local gas function * coremark benches show ~20% performance improvement * fix ci: test + clippy * save before re-factoring prepare_in_wasm() * bare_call_16 shows 16% worse perf * + fibonacci recursive bench * refactored benchmarks * + factorial recursive bench * benches on wasmi fixtures show no perf improvement, coremark runs ~20% faster being instrumented with mutable_global gas metering * charge gas for local gas func isntructions execution * replaced benchmark which requires multi_value feature * save: optimized gas func a bit (benches work, fixture tests fail) * 1033% overhead on many_blocks.wasm when mut_global gas_metering together with stack_height * size overhead test for both gas metering methods + stack limiter * added more benches * improved print_size_overhead test * test for comparing size overheads of two gas_metering injectors * before optimization: benches + size overhead * optimization try-1: inline part of gas func instructions: +benches +size overheads * optimization try-2: inline hot path of gas fn: +benches +size overheads * opt try-3: count for gas fn cost on the caller side: +benches +size overhead * revert to initial version but with static gas fn cost on the caller side: +benches +sizes * tests fixed * use newest wasmi 0.20: +benches +docs updated * use if-else block instead of Return: +benches * fix tests * clippy fix * addressed review comments * Update changelog Co-authored-by: Alexander Theißen <alex.theissen@me.com>
This commit is contained in:
+64
-29
@@ -1,10 +1,9 @@
|
||||
use parity_wasm::elements::Module;
|
||||
use std::{
|
||||
fs,
|
||||
io::{self, Read, Write},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use wasm_instrument::{self as instrument, parity_wasm::elements};
|
||||
use wasm_instrument::{self as instrument, gas_metering, parity_wasm::elements};
|
||||
use wasmparser::validate;
|
||||
|
||||
fn slurp<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
|
||||
@@ -20,18 +19,23 @@ fn dump<P: AsRef<Path>>(path: P, buf: &[u8]) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_diff_test<F: FnOnce(&[u8]) -> Vec<u8>>(test_dir: &str, name: &str, test: F) {
|
||||
fn run_diff_test<F: FnOnce(&[u8]) -> Vec<u8>>(
|
||||
test_dir: &str,
|
||||
in_name: &str,
|
||||
out_name: &str,
|
||||
test: F,
|
||||
) {
|
||||
let mut fixture_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
fixture_path.push("tests");
|
||||
fixture_path.push("fixtures");
|
||||
fixture_path.push(test_dir);
|
||||
fixture_path.push(name);
|
||||
fixture_path.push(in_name);
|
||||
|
||||
let mut expected_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
expected_path.push("tests");
|
||||
expected_path.push("expectations");
|
||||
expected_path.push(test_dir);
|
||||
expected_path.push(name);
|
||||
expected_path.push(out_name);
|
||||
|
||||
let fixture_wasm = wat::parse_file(&fixture_path).expect("Failed to read fixture");
|
||||
validate(&fixture_wasm).expect("Fixture is invalid");
|
||||
@@ -48,7 +52,7 @@ fn run_diff_test<F: FnOnce(&[u8]) -> Vec<u8>>(test_dir: &str, name: &str, test:
|
||||
if actual_wat != expected_wat {
|
||||
println!("difference!");
|
||||
println!("--- {}", expected_path.display());
|
||||
println!("+++ {} test {}", test_dir, name);
|
||||
println!("+++ {} test {}", test_dir, out_name);
|
||||
for diff in diff::lines(expected_wat, &actual_wat) {
|
||||
match diff {
|
||||
diff::Result::Left(l) => println!("-{}", l),
|
||||
@@ -72,13 +76,18 @@ mod stack_height {
|
||||
( $name:ident ) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
run_diff_test("stack-height", concat!(stringify!($name), ".wat"), |input| {
|
||||
let module =
|
||||
elements::deserialize_buffer(input).expect("Failed to deserialize");
|
||||
let instrumented = instrument::inject_stack_limiter(module, 1024)
|
||||
.expect("Failed to instrument with stack counter");
|
||||
elements::serialize(instrumented).expect("Failed to serialize")
|
||||
});
|
||||
run_diff_test(
|
||||
"stack-height",
|
||||
concat!(stringify!($name), ".wat"),
|
||||
concat!(stringify!($name), ".wat"),
|
||||
|input| {
|
||||
let module =
|
||||
elements::deserialize_buffer(input).expect("Failed to deserialize");
|
||||
let instrumented = instrument::inject_stack_limiter(module, 1024)
|
||||
.expect("Failed to instrument with stack counter");
|
||||
elements::serialize(instrumented).expect("Failed to serialize")
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -96,27 +105,53 @@ mod gas {
|
||||
use super::*;
|
||||
|
||||
macro_rules! def_gas_test {
|
||||
( $name:ident ) => {
|
||||
( ($input:ident, $name1:ident, $name2:ident) ) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
run_diff_test("gas", concat!(stringify!($name), ".wat"), |input| {
|
||||
let rules = instrument::gas_metering::ConstantCostRules::default();
|
||||
fn $name1() {
|
||||
run_diff_test(
|
||||
"gas",
|
||||
concat!(stringify!($input), ".wat"),
|
||||
concat!(stringify!($name1), ".wat"),
|
||||
|input| {
|
||||
let rules = gas_metering::ConstantCostRules::default();
|
||||
|
||||
let module: Module =
|
||||
elements::deserialize_buffer(input).expect("Failed to deserialize");
|
||||
let module = module.parse_names().expect("Failed to parse names");
|
||||
let module: elements::Module =
|
||||
elements::deserialize_buffer(input).expect("Failed to deserialize");
|
||||
let module = module.parse_names().expect("Failed to parse names");
|
||||
let backend = gas_metering::host_function::Injector::new("env", "gas");
|
||||
|
||||
let instrumented = instrument::gas_metering::inject(module, &rules, "env")
|
||||
.expect("Failed to instrument with gas metering");
|
||||
elements::serialize(instrumented).expect("Failed to serialize")
|
||||
});
|
||||
let instrumented = gas_metering::inject(module, backend, &rules)
|
||||
.expect("Failed to instrument with gas metering");
|
||||
elements::serialize(instrumented).expect("Failed to serialize")
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn $name2() {
|
||||
run_diff_test(
|
||||
"gas",
|
||||
concat!(stringify!($input), ".wat"),
|
||||
concat!(stringify!($name2), ".wat"),
|
||||
|input| {
|
||||
let rules = gas_metering::ConstantCostRules::default();
|
||||
|
||||
let module: elements::Module =
|
||||
elements::deserialize_buffer(input).expect("Failed to deserialize");
|
||||
let module = module.parse_names().expect("Failed to parse names");
|
||||
let backend = gas_metering::mutable_global::Injector::new("gas_left");
|
||||
let instrumented = gas_metering::inject(module, backend, &rules)
|
||||
.expect("Failed to instrument with gas metering");
|
||||
elements::serialize(instrumented).expect("Failed to serialize")
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
def_gas_test!(ifs);
|
||||
def_gas_test!(simple);
|
||||
def_gas_test!(start);
|
||||
def_gas_test!(call);
|
||||
def_gas_test!(branch);
|
||||
def_gas_test!((ifs, ifs_host_fn, ifs_mut_global));
|
||||
def_gas_test!((simple, simple_host_fn, simple_mut_global));
|
||||
def_gas_test!((start, start_host_fn, start_mut_global));
|
||||
def_gas_test!((call, call_host_fn, call_mut_global));
|
||||
def_gas_test!((branch, branch_host_fn, branch_mut_global));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user