Skip to content

Commit cc5c1fa

Browse files
authored
Vm benchmark tests (#299)
Vm microbenchmark consists of few tests: - compressions (deflate and snappy) - factorization - matrix QR decompostion - matrix SVD decompostion - matrix product - sha3 hash computing - recurive fibonacci computing Each test exports the `main` function and contains few compile-time parameters that can be adjusted using the corresponding environment variables.
1 parent d639b26 commit cc5c1fa

File tree

29 files changed

+717
-0
lines changed

29 files changed

+717
-0
lines changed

bench/vm/tests/README.md

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
## VM benchmark tests
2+
3+
This microbenchmark consists of a few tests which can be used to measure performance of various WebAssembly virtual machines. It should be noted this benchmark is by definition is not comprehensive and might not reflect performance on real life workloads.
4+
5+
However, each test was crafted in a way that would prevent the virtual machine from optimizing them using the dead code elimination. Most tests also prevent intermediate results memoization (with `fibonacci_bigint` and `factorization_reikna` being exceptions) and allow to specify an RNG seed to obtain repeatable benchmark results.
6+
7+
Each test exports the `main` function which is called by the benchmark runner. There are also few compile-time parameters in each test that can be adjusted using the corresponding environment variables. The benchmark has been successfully tested on Mac and should run smoothly on Linux as well.
8+
9+
To run tests Rust Cargo package manager should be installed – the easiest way would be to follow these instructions:
10+
11+
```shell
12+
# download and install rustup
13+
curl -sSf https://static.rust-lang.org/rustup.sh | sh
14+
15+
# install the latest nightly toolchain
16+
~/.cargo/bin/rustup toolchain install nightly
17+
18+
# make shure that Rust is up to date
19+
rustup update
20+
21+
# install the Webassembly target for Rust
22+
rustup target add wasm32-unknown-unknown --toolchain nightly
23+
```
24+
Below we also assume that Fluence GitHub repo has been already cloned and we are in the `vm_bench/tests` directory:
25+
26+
```shell
27+
git clone --recursive https://github.com/fluencelabs/fluence
28+
cd fluence/vm/vm_bench/tests
29+
```
30+
31+
Random numbers in tests are generated with [IsaacRng](https://doc.rust-lang.org/1.0.0/rand/isaac/struct.IsaacRng.html). It should also be noted relative results of the QR and SVG decomposition tests can be somewhat different on different hardware because of the floating point non-determinism.
32+
33+
### Compression
34+
35+
This test compresses a sequence of `SEQUENCE_SIZE` bytes and has `ITERATIONS_COUNT` iterations of compressions. On each iteration a new sequence is generated by the seed that was computed based on the previous sequence. As the first seed the `SEED` parameter is used. Two compression algorithms ([deflate](https://docs.rs/deflate) and [snappy](https://docs.rs/snap)) are supported and can be chosen by specifying the `deflate_compression` flag.
36+
37+
To run:
38+
39+
```shell
40+
cd recursive_hash
41+
ITERATIONS_COUNT=1 SEED=1000000 SEQUENCE_SIZE=1024 cargo build --release --target wasm32-unknown-unknown [--feature "deflate_compression"]
42+
```
43+
44+
### Factorization
45+
46+
This test factorizes provided `FACTORIZED_NUMBER` using [reikna](https://docs.rs/reikna/0.10.0/reikna/) library.
47+
48+
To run:
49+
50+
```shell
51+
cd factorization_reikna
52+
FACTORIZED_NUMBER=2147483647 cargo build --release --target wasm32-unknown-unknown
53+
```
54+
55+
### Recursive fibonacci computing
56+
57+
This test recursively computes the Fibonacci number with the index `FIB_NUMBER`.
58+
59+
To run:
60+
61+
```shell
62+
cd fibonacci_bigint
63+
FIB_NUMBER=38 cargo build --release --target wasm32-unknown-unknown
64+
```
65+
66+
### Matrix product
67+
68+
This test computes a product of random generated matrices of size `MATRIX_SIZE`. There are `ITERATIONS_COUNT` iterations; on each iteration new matrices are generated using the seed that was computed using the previous product result. As the first seed the `SEED` parameter is used.
69+
70+
To run:
71+
72+
```shell
73+
cd matrix_product
74+
ITERATIONS_COUNT=1000000 SEED=1 MATRIX_SIZE=10 cargo build --release --target wasm32-unknown-unknown
75+
```
76+
77+
### Matrix QR decomposition
78+
79+
This test computes a QR decomposition of random generated matrices of size `MATRIX_SIZE`. There are `ITERATIONS_COUNT` iterations of decomposition; on each iteration a new matrix is generated using the seed that was computed using the previous decomposition result. As the first seed the `SEED` parameter is used.
80+
81+
To run:
82+
83+
```shell
84+
cd matrix_qr_decomposition
85+
ITERATIONS_COUNT=1000000 SEED=1 MATRIX_SIZE=10 cargo build --release --target wasm32-unknown-unknown
86+
```
87+
88+
### Matrix SVD decomposition
89+
90+
This test computes an SVD decomposition of random generated matrices of size `MATRIX_SIZE`. There are `ITERATIONS_COUNT` iterations of decomposition; on each iteration a new matrix is generated using the seed that was computed using the previous decomposition result. As the first seed the `SEED` parameter is used.
91+
92+
To run:
93+
94+
```shell
95+
cd matrix_svd_decomposition
96+
ITERATIONS_COUNT=1000000 SEED=1 MATRIX_SIZE=10 cargo build --release --target wasm32-unknown-unknown
97+
```
98+
99+
### Recursive hash computing
100+
101+
This test iteratively computes a hash chain `hash(hash( ... hash(x)))` of length `ITERATIONS_COUNT`, where `x` is the initial value specified by `INITIAL_VALUE`.
102+
103+
To run:
104+
105+
```shell
106+
cd recursive_hash
107+
ITERATIONS_COUNT=10000000 INITIAL_VALUE=0 cargo build --release --target wasm32-unknown-unknown
108+
```

bench/vm/tests/compression/Cargo.toml

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "compression"
3+
version = "0.1.0"
4+
authors = ["Fluence Labs"]
5+
6+
[lib]
7+
crate-type = ["cdylib"]
8+
9+
[dependencies]
10+
snap = "0.2"
11+
deflate = "0.7.19"
12+
rand = "0.6.1"
13+
rand_isaac = "0.1.0"
14+
15+
[features]
16+
default = []
17+
deflate_compression = []
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nightly

bench/vm/tests/compression/src/lib.rs

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2018 Fluence Labs Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
mod settings;
17+
18+
extern crate deflate;
19+
extern crate rand;
20+
extern crate rand_isaac;
21+
extern crate snap;
22+
23+
use deflate::deflate_bytes;
24+
use rand::{Rng, SeedableRng};
25+
use rand_isaac::IsaacRng;
26+
use settings::{ITERATIONS_COUNT, SEED, SEQUENCE_SIZE};
27+
28+
type Sequence = Vec<u8>;
29+
30+
/// Generates pseudo-random byte sequence by given seed and given size.
31+
fn generate_sequence(seed: u64, size: usize) -> Sequence {
32+
let mut rng: IsaacRng = SeedableRng::seed_from_u64(seed);
33+
let mut result_sequence = Sequence::with_capacity(size);
34+
35+
for _ in 0..size {
36+
result_sequence.push(rng.gen::<u8>());
37+
}
38+
result_sequence
39+
}
40+
41+
/// Compresses provided sequence by deflate or snappy algorithm.
42+
fn compress_sequence(sequence: &Sequence) -> Sequence {
43+
if cfg!(feature = "deflate_compression") {
44+
return deflate_bytes(&sequence);
45+
}
46+
47+
return snap::Encoder::new().compress_vec(&sequence).unwrap();
48+
}
49+
50+
#[no_mangle]
51+
pub extern "C" fn main() -> u8 {
52+
let seed: u64 = SEED.parse::<u64>().unwrap();
53+
let iterations_count: u64 = ITERATIONS_COUNT.parse::<u64>().unwrap();
54+
let sequence_size: usize = SEQUENCE_SIZE.parse::<usize>().unwrap();
55+
56+
let mut compressed_sequence = generate_sequence(seed, sequence_size);
57+
58+
for _ in 1..iterations_count {
59+
let new_seed: usize = compressed_sequence.len()
60+
+ compressed_sequence.iter().fold(0u8, |x1, x2| x1 ^ x2) as usize;
61+
compressed_sequence = generate_sequence(new_seed as u64, sequence_size);
62+
compressed_sequence = compress_sequence(&compressed_sequence);
63+
}
64+
65+
compressed_sequence.iter().fold(0u8, |x1, x2| x1 ^ x2)
66+
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2018 Fluence Labs Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
/// This value is used as the first seed of pseudo-random generator for sequence generation.
17+
pub const SEED: &str = env!("SEED");
18+
19+
/// Count of compression iterations.
20+
pub const ITERATIONS_COUNT: &str = env!("ITERATIONS_COUNT");
21+
22+
/// Size of sequence that should be compressed on each iteration.
23+
pub const SEQUENCE_SIZE: &str = env!("SEQUENCE_SIZE");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "factorization_reikna"
3+
version = "0.1.0"
4+
authors = ["Fluence Labs"]
5+
6+
[lib]
7+
crate-type = ["cdylib"]
8+
9+
[dependencies]
10+
reikna = "0.6.0"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nightly
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2018 Fluence Labs Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
mod settings;
17+
extern crate reikna;
18+
19+
use reikna::prime;
20+
use settings::FACTORIZED_NUMBER;
21+
22+
#[no_mangle]
23+
pub extern "C" fn main() -> u64 {
24+
let factorized_number: u64 = FACTORIZED_NUMBER.parse::<u64>().unwrap();
25+
// reikna uses Atkin or Eratosthenes seive to factorize given number
26+
let factors = prime::factorize(factorized_number);
27+
28+
factors[0]
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright 2018 Fluence Labs Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
/// A requested number that should be factorized by this test.
17+
pub const FACTORIZED_NUMBER: &str = env!("FACTORIZED_NUMBER");
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "fibonacci_bigint"
3+
version = "0.1.0"
4+
authors = ["Fluence Labs"]
5+
6+
[lib]
7+
crate-type = ["cdylib"]
8+
9+
[dependencies]
10+
num-bigint = "0.2"
11+
num-traits = "0.2"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nightly
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2018 Fluence Labs Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
mod settings;
17+
extern crate num_bigint;
18+
extern crate num_traits;
19+
20+
use num_bigint::BigUint;
21+
use num_traits::One;
22+
use settings::FIB_NUMBER;
23+
use std::ops::Sub;
24+
25+
/// Recursively computes a fibonacci number F_num for the given num.
26+
fn fib(num: &BigUint) -> BigUint {
27+
if num.le(&BigUint::from(2u32)) {
28+
return One::one();
29+
}
30+
31+
fib(&num.sub(1u32)) + fib(&num.sub(2u32))
32+
}
33+
34+
#[no_mangle]
35+
pub extern "C" fn main() -> u8 {
36+
let fib_number: BigUint = BigUint::from(FIB_NUMBER.parse::<u64>().unwrap());
37+
38+
fib(&fib_number)
39+
.to_bytes_le()
40+
.iter()
41+
.fold(0u8, |x1, x2| x1 ^ x2)
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright 2018 Fluence Labs Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
/// A requested fibonacci number that would be computed.
17+
pub const FIB_NUMBER: &str = env!("FIB_NUMBER");
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "matrix_product"
3+
version = "0.1.0"
4+
authors = ["Fluence Labs"]
5+
6+
[lib]
7+
crate-type = ["cdylib"]
8+
9+
[dependencies]
10+
nalgebra = { version = "0.16", features = [ "alloc" ] }
11+
rand = "0.6.1"
12+
rand_isaac = "0.1.0"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nightly

0 commit comments

Comments
 (0)