diff --git a/.travis.yml b/.travis.yml index 03c14d8..3cf1344 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,9 @@ sudo: required language: - rust - cpp +rust: + - nightly + - stable addons: apt: sources: @@ -12,18 +15,16 @@ addons: - g++-6 - cmake env: -- NIGHTLY_TOOLCHAIN=nightly-2018-02-05 +- CC=/usr/bin/gcc-6 CXX=/usr/bin/g++-6 install: # Install `cargo-deadlinks` unless it is currently installed. - command -v cargo-deadlinks &> /dev/null || cargo install cargo-deadlinks -# Install nightly toolchain. -- rustup toolchain install $NIGHTLY_TOOLCHAIN +- if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then rustup target add wasm32-unknown-unknown; fi script: -- export CC=/usr/bin/gcc-6 -- export CXX=/usr/bin/g++-6 # Make sure fuzz targets are not broken. -- rustup run $NIGHTLY_TOOLCHAIN cargo check --tests --manifest-path=fuzz/Cargo.toml +- if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then cargo check --tests --manifest-path=fuzz/Cargo.toml; fi +- if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then cargo check --benches --manifest-path=benches/Cargo.toml; fi - ./test.sh - ./doc.sh after_success: | diff --git a/Cargo.toml b/Cargo.toml index 6014301..b74d752 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/paritytech/wasmi" documentation = "https://paritytech.github.io/wasmi/" description = "WebAssembly interpreter" keywords = ["wasm", "webassembly", "bytecode", "interpreter"] -exclude = [ "/res/*", "/tests/*", "/fuzz/*" ] +exclude = [ "/res/*", "/tests/*", "/fuzz/*", "/benches/*" ] [dependencies] parity-wasm = "0.27" diff --git a/benches/.gitignore b/benches/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/benches/.gitignore @@ -0,0 +1 @@ +/target diff --git a/benches/Cargo.toml b/benches/Cargo.toml new file mode 100644 index 0000000..0df6e79 --- /dev/null +++ b/benches/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "benches" +version = "0.1.0" +authors = ["Sergey Pepyakin "] + +[dependencies] +wasmi = { path = ".." } +assert_matches = "1.2" diff --git a/benches/build.rs b/benches/build.rs new file mode 100644 index 0000000..9cb9ac1 --- /dev/null +++ b/benches/build.rs @@ -0,0 +1,32 @@ +use std::env; +use std::process; + + +fn main() { + println!("cargo:rerun-if-changed=./wasm-kernel/"); + + // The CARGO environment variable provides a path to the executable that + // runs this build process. + let cargo_bin = env::var("CARGO").expect("CARGO env variable should be defined"); + + // Build a release version of wasm-kernel. The code in the output wasm binary + // will be used in benchmarks. + let output = process::Command::new(cargo_bin) + .arg("build") + .arg("--target=wasm32-unknown-unknown") + .arg("--release") + .arg("--manifest-path=./wasm-kernel/Cargo.toml") + .arg("--verbose") + .output() + .expect("failed to execute `cargo`"); + + if !output.status.success() { + let msg = format!( + "status: {status}\nstdout: {stdout}\nstderr: {stderr}\n", + status=output.status, + stdout=String::from_utf8_lossy(&output.stdout), + stderr=String::from_utf8_lossy(&output.stderr), + ); + panic!("{}", msg); + } +} diff --git a/benches/src/lib.rs b/benches/src/lib.rs new file mode 100644 index 0000000..db01ccd --- /dev/null +++ b/benches/src/lib.rs @@ -0,0 +1,43 @@ +#![feature(test)] + +extern crate test; +extern crate wasmi; +#[macro_use] +extern crate assert_matches; + +use std::error; +use std::fs::File; +use wasmi::{ImportsBuilder, Module, ModuleInstance, NopExternals, RuntimeValue}; + +use test::Bencher; + +// Load a module from a file. +fn load_from_file(filename: &str) -> Result> { + use std::io::prelude::*; + let mut file = File::open(filename)?; + let mut buf = Vec::new(); + file.read_to_end(&mut buf)?; + Ok(Module::from_buffer(buf)?) +} + +#[bench] +fn bench_tiny_keccak(b: &mut Bencher) { + let wasm_kernel = load_from_file( + "./wasm-kernel/target/wasm32-unknown-unknown/release/wasm_kernel.wasm", + ).expect("failed to load wasm_kernel. Is `build.rs` broken?"); + + let instance = ModuleInstance::new(&wasm_kernel, &ImportsBuilder::default()) + .expect("failed to instantiate wasm module") + .assert_no_start(); + + let test_data_ptr = assert_matches!( + instance.invoke_export("prepare_tiny_keccak", &[], &mut NopExternals), + Ok(Some(v @ RuntimeValue::I32(_))) => v + ); + + b.iter(|| { + instance + .invoke_export("bench_tiny_keccak", &[test_data_ptr], &mut NopExternals) + .unwrap(); + }); +} diff --git a/benches/wasm-kernel/.gitignore b/benches/wasm-kernel/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/benches/wasm-kernel/.gitignore @@ -0,0 +1 @@ +/target diff --git a/benches/wasm-kernel/Cargo.toml b/benches/wasm-kernel/Cargo.toml new file mode 100644 index 0000000..f9717f5 --- /dev/null +++ b/benches/wasm-kernel/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "wasm-kernel" +version = "0.1.0" +authors = ["Sergey Pepyakin "] + +[lib] +crate-type = ["cdylib"] + +[dependencies] +tiny-keccak = "1.4.2" +rlibc = "1.0" + +[profile.release] +panic = "abort" +lto = true +opt-level = "z" diff --git a/benches/wasm-kernel/src/lib.rs b/benches/wasm-kernel/src/lib.rs new file mode 100644 index 0000000..39a6372 --- /dev/null +++ b/benches/wasm-kernel/src/lib.rs @@ -0,0 +1,54 @@ +#![no_std] +#![feature(lang_items)] +#![feature(core_intrinsics)] + +extern crate rlibc; +extern crate tiny_keccak; + +use tiny_keccak::Keccak; + +#[no_mangle] +#[lang = "panic_fmt"] +pub extern "C" fn panic_fmt( + _args: ::core::fmt::Arguments, + _file: &'static str, + _line: u32, + _col: u32, +) -> ! { + use core::intrinsics; + unsafe { + intrinsics::abort(); + } +} + +pub struct TinyKeccakTestData { + data: &'static [u8], + result: &'static mut [u8], +} + +#[no_mangle] +pub extern "C" fn prepare_tiny_keccak() -> *const TinyKeccakTestData { + static DATA: [u8; 4096] = [254u8; 4096]; + static mut RESULT: [u8; 32] = [0u8; 32]; + + static mut TEST_DATA: Option = None; + + unsafe { + if let None = TEST_DATA { + TEST_DATA = Some(TinyKeccakTestData { + data: &DATA, + result: &mut RESULT, + }); + } + TEST_DATA.as_ref().unwrap() as *const TinyKeccakTestData + } +} + +#[no_mangle] +pub extern "C" fn bench_tiny_keccak(test_data: *const TinyKeccakTestData) { + unsafe { + let mut keccak = Keccak::new_keccak256(); + keccak.update((*test_data).data); + keccak.finalize((*test_data).result); + } +} diff --git a/doc.sh b/doc.sh index 5148060..652db79 100755 --- a/doc.sh +++ b/doc.sh @@ -4,11 +4,7 @@ set -eux cd $(dirname $0) -if [ -s NIGHTLY_TOOLCHAIN ]; then - rustup run $NIGHTLY_TOOLCHAIN cargo doc -else - cargo doc -fi; +cargo doc # cargo-deadlinks will check any links in docs generated by `cargo doc`. # This is useful as rustdoc uses raw links which are error prone.