#![feature(test)] /// Unfortunately, `cargo bench` does not permit running these benchmarks out-of-the-box /// on a WebAssembly virtual machine. /// /// Follow these steps to run these benchmarks: /// 0. Prerequisites: Install the `wasm32-wasi` target and `wasmer` /// /// /// 1. Build these benchmarks /// ```bash /// cargo build --bench=bench_rustfft_wasm_simd --release --target wasm32-wasi --features "wasm_simd" /// ``` /// /// After cargo built the bench binary, cargo stores it inside the /// `/target/wasm32-wasi/release/deps` directory. /// The file name of this binary follows this format: `bench_rustfft_wasm_simd-.wasm`. /// For instance, it could be named /// `target/wasm32-wasi/release/deps/bench_rustfft_scalar-6d2b3d5a567416f5.wasm` /// /// 2. Copy the most recently built WASM binary to hex.wasm /// ```bash /// cp `ls -t target/wasm32-wasi/release/deps/*.wasm | head -n 1` hex.wasm /// ``` /// /// 3. Run these benchmark e. g. with [wasmer](https://github.com/wasmerio/wasmer) /// ```bash /// wasmer run --dir=. hex.wasm -- --bench /// ``` /// /// For more information, refer to [Criterion's user guide](https://github.com/bheisler/criterion.rs/blob/dc2b06cd31f7aa34cff6a83a00598e0523186dad/book/src/user_guide/wasi.md) /// which should be mostly applicable to our use case. extern crate rustfft; extern crate test; use rustfft::num_complex::Complex; use rustfft::num_traits::Zero; use rustfft::Fft; use std::sync::Arc; use test::Bencher; /// Times just the FFT execution (not allocation and pre-calculation) /// for a given length fn bench_planned_f32(b: &mut Bencher, len: usize) { let mut planner = rustfft::FftPlannerWasmSimd::new().unwrap(); let fft: Arc> = planner.plan_fft_forward(len); assert_eq!(fft.len(), len); let mut buffer = vec![Complex::zero(); len]; let mut scratch = vec![Complex::zero(); fft.get_inplace_scratch_len()]; b.iter(|| { fft.process_with_scratch(&mut buffer, &mut scratch); }); } fn bench_planned_f64(b: &mut Bencher, len: usize) { let mut planner = rustfft::FftPlannerWasmSimd::new().unwrap(); let fft: Arc> = planner.plan_fft_forward(len); assert_eq!(fft.len(), len); let mut buffer = vec![Complex::zero(); len]; let mut scratch = vec![Complex::zero(); fft.get_inplace_scratch_len()]; b.iter(|| { fft.process_with_scratch(&mut buffer, &mut scratch); }); } /// Times just the FFT execution (not allocation and pre-calculation) /// for a given length. /// Run the fft on a 10*len vector, similar to how the butterflies are often used. fn bench_planned_multi_f32(b: &mut Bencher, len: usize) { let mut planner = rustfft::FftPlannerWasmSimd::new().unwrap(); let fft: Arc> = planner.plan_fft_forward(len); let mut buffer = vec![Complex::zero(); len * 10]; let mut scratch = vec![Complex::zero(); fft.get_inplace_scratch_len()]; b.iter(|| { fft.process_with_scratch(&mut buffer, &mut scratch); }); } fn bench_planned_multi_f64(b: &mut Bencher, len: usize) { let mut planner = rustfft::FftPlannerWasmSimd::new().unwrap(); let fft: Arc> = planner.plan_fft_forward(len); let mut buffer = vec![Complex::zero(); len * 10]; let mut scratch = vec![Complex::zero(); fft.get_inplace_scratch_len()]; b.iter(|| { fft.process_with_scratch(&mut buffer, &mut scratch); }); } // All butterflies #[bench] fn wasm_simd_butterfly32_02(b: &mut Bencher) { bench_planned_multi_f32(b, 2); } #[bench] fn wasm_simd_butterfly32_03(b: &mut Bencher) { bench_planned_multi_f32(b, 3); } #[bench] fn wasm_simd_butterfly32_04(b: &mut Bencher) { bench_planned_multi_f32(b, 4); } #[bench] fn wasm_simd_butterfly32_05(b: &mut Bencher) { bench_planned_multi_f32(b, 5); } #[bench] fn wasm_simd_butterfly32_06(b: &mut Bencher) { bench_planned_multi_f32(b, 6); } #[bench] fn wasm_simd_butterfly32_07(b: &mut Bencher) { bench_planned_multi_f32(b, 7); } #[bench] fn wasm_simd_butterfly32_08(b: &mut Bencher) { bench_planned_multi_f32(b, 8); } #[bench] fn wasm_simd_butterfly32_09(b: &mut Bencher) { bench_planned_multi_f32(b, 9); } #[bench] fn wasm_simd_butterfly32_10(b: &mut Bencher) { bench_planned_multi_f32(b, 10); } #[bench] fn wasm_simd_butterfly32_11(b: &mut Bencher) { bench_planned_multi_f32(b, 11); } #[bench] fn wasm_simd_butterfly32_12(b: &mut Bencher) { bench_planned_multi_f32(b, 12); } #[bench] fn wasm_simd_butterfly32_13(b: &mut Bencher) { bench_planned_multi_f32(b, 13); } #[bench] fn wasm_simd_butterfly32_15(b: &mut Bencher) { bench_planned_multi_f32(b, 15); } #[bench] fn wasm_simd_butterfly32_16(b: &mut Bencher) { bench_planned_multi_f32(b, 16); } #[bench] fn wasm_simd_butterfly32_17(b: &mut Bencher) { bench_planned_multi_f32(b, 17); } #[bench] fn wasm_simd_butterfly32_19(b: &mut Bencher) { bench_planned_multi_f32(b, 19); } #[bench] fn wasm_simd_butterfly32_23(b: &mut Bencher) { bench_planned_multi_f32(b, 23); } #[bench] fn wasm_simd_butterfly32_29(b: &mut Bencher) { bench_planned_multi_f32(b, 29); } #[bench] fn wasm_simd_butterfly32_31(b: &mut Bencher) { bench_planned_multi_f32(b, 31); } #[bench] fn wasm_simd_butterfly32_32(b: &mut Bencher) { bench_planned_multi_f32(b, 32); } #[bench] fn wasm_simd_butterfly64_02(b: &mut Bencher) { bench_planned_multi_f64(b, 2); } #[bench] fn wasm_simd_butterfly64_03(b: &mut Bencher) { bench_planned_multi_f64(b, 3); } #[bench] fn wasm_simd_butterfly64_04(b: &mut Bencher) { bench_planned_multi_f64(b, 4); } #[bench] fn wasm_simd_butterfly64_05(b: &mut Bencher) { bench_planned_multi_f64(b, 5); } #[bench] fn wasm_simd_butterfly64_06(b: &mut Bencher) { bench_planned_multi_f64(b, 6); } #[bench] fn wasm_simd_butterfly64_07(b: &mut Bencher) { bench_planned_multi_f64(b, 7); } #[bench] fn wasm_simd_butterfly64_08(b: &mut Bencher) { bench_planned_multi_f64(b, 8); } #[bench] fn wasm_simd_butterfly64_09(b: &mut Bencher) { bench_planned_multi_f64(b, 9); } #[bench] fn wasm_simd_butterfly64_10(b: &mut Bencher) { bench_planned_multi_f64(b, 10); } #[bench] fn wasm_simd_butterfly64_11(b: &mut Bencher) { bench_planned_multi_f64(b, 11); } #[bench] fn wasm_simd_butterfly64_12(b: &mut Bencher) { bench_planned_multi_f64(b, 12); } #[bench] fn wasm_simd_butterfly64_13(b: &mut Bencher) { bench_planned_multi_f64(b, 13); } #[bench] fn wasm_simd_butterfly64_15(b: &mut Bencher) { bench_planned_multi_f64(b, 15); } #[bench] fn wasm_simd_butterfly64_16(b: &mut Bencher) { bench_planned_multi_f64(b, 16); } #[bench] fn wasm_simd_butterfly64_17(b: &mut Bencher) { bench_planned_multi_f64(b, 17); } #[bench] fn wasm_simd_butterfly64_19(b: &mut Bencher) { bench_planned_multi_f64(b, 19); } #[bench] fn wasm_simd_butterfly64_23(b: &mut Bencher) { bench_planned_multi_f64(b, 23); } #[bench] fn wasm_simd_butterfly64_29(b: &mut Bencher) { bench_planned_multi_f64(b, 29); } #[bench] fn wasm_simd_butterfly64_31(b: &mut Bencher) { bench_planned_multi_f64(b, 31); } #[bench] fn wasm_simd_butterfly64_32(b: &mut Bencher) { bench_planned_multi_f64(b, 32); } // Powers of 2 #[bench] fn wasm_simd_planned32_p2_00000064(b: &mut Bencher) { bench_planned_f32(b, 64); } #[bench] fn wasm_simd_planned32_p2_00000128(b: &mut Bencher) { bench_planned_f32(b, 128); } #[bench] fn wasm_simd_planned32_p2_00000256(b: &mut Bencher) { bench_planned_f32(b, 256); } #[bench] fn wasm_simd_planned32_p2_00000512(b: &mut Bencher) { bench_planned_f32(b, 512); } #[bench] fn wasm_simd_planned32_p2_00001024(b: &mut Bencher) { bench_planned_f32(b, 1024); } #[bench] fn wasm_simd_planned32_p2_00002048(b: &mut Bencher) { bench_planned_f32(b, 2048); } #[bench] fn wasm_simd_planned32_p2_00004096(b: &mut Bencher) { bench_planned_f32(b, 4096); } #[bench] fn wasm_simd_planned32_p2_00016384(b: &mut Bencher) { bench_planned_f32(b, 16384); } #[bench] fn wasm_simd_planned32_p2_00065536(b: &mut Bencher) { bench_planned_f32(b, 65536); } #[bench] fn wasm_simd_planned32_p2_01048576(b: &mut Bencher) { bench_planned_f32(b, 1048576); } #[bench] fn wasm_simd_planned64_p2_00000064(b: &mut Bencher) { bench_planned_f64(b, 64); } #[bench] fn wasm_simd_planned64_p2_00000128(b: &mut Bencher) { bench_planned_f64(b, 128); } #[bench] fn wasm_simd_planned64_p2_00000256(b: &mut Bencher) { bench_planned_f64(b, 256); } #[bench] fn wasm_simd_planned64_p2_00000512(b: &mut Bencher) { bench_planned_f64(b, 512); } #[bench] fn wasm_simd_planned64_p2_00001024(b: &mut Bencher) { bench_planned_f64(b, 1024); } #[bench] fn wasm_simd_planned64_p2_00002048(b: &mut Bencher) { bench_planned_f64(b, 2048); } #[bench] fn wasm_simd_planned64_p2_00004096(b: &mut Bencher) { bench_planned_f64(b, 4096); } #[bench] fn wasm_simd_planned64_p2_00016384(b: &mut Bencher) { bench_planned_f64(b, 16384); } #[bench] fn wasm_simd_planned64_p2_00065536(b: &mut Bencher) { bench_planned_f64(b, 65536); } #[bench] fn wasm_simd_planned64_p2_01048576(b: &mut Bencher) { bench_planned_f64(b, 1048576); } // Powers of 7 #[bench] fn wasm_simd_planned32_p7_00343(b: &mut Bencher) { bench_planned_f32(b, 343); } #[bench] fn wasm_simd_planned32_p7_02401(b: &mut Bencher) { bench_planned_f32(b, 2401); } #[bench] fn wasm_simd_planned32_p7_16807(b: &mut Bencher) { bench_planned_f32(b, 16807); } #[bench] fn wasm_simd_planned64_p7_00343(b: &mut Bencher) { bench_planned_f64(b, 343); } #[bench] fn wasm_simd_planned64_p7_02401(b: &mut Bencher) { bench_planned_f64(b, 2401); } #[bench] fn wasm_simd_planned64_p7_16807(b: &mut Bencher) { bench_planned_f64(b, 16807); } // Prime lengths #[bench] fn wasm_simd_planned32_prime_0149(b: &mut Bencher) { bench_planned_f32(b, 149); } #[bench] fn wasm_simd_planned32_prime_0151(b: &mut Bencher) { bench_planned_f32(b, 151); } #[bench] fn wasm_simd_planned32_prime_0251(b: &mut Bencher) { bench_planned_f32(b, 251); } #[bench] fn wasm_simd_planned32_prime_0257(b: &mut Bencher) { bench_planned_f32(b, 257); } #[bench] fn wasm_simd_planned32_prime_2017(b: &mut Bencher) { bench_planned_f32(b, 2017); } #[bench] fn wasm_simd_planned32_prime_2879(b: &mut Bencher) { bench_planned_f32(b, 2879); } #[bench] fn wasm_simd_planned32_prime_65521(b: &mut Bencher) { bench_planned_f32(b, 65521); } #[bench] fn wasm_simd_planned32_prime_746497(b: &mut Bencher) { bench_planned_f32(b, 746497); } #[bench] fn wasm_simd_planned64_prime_0149(b: &mut Bencher) { bench_planned_f64(b, 149); } #[bench] fn wasm_simd_planned64_prime_0151(b: &mut Bencher) { bench_planned_f64(b, 151); } #[bench] fn wasm_simd_planned64_prime_0251(b: &mut Bencher) { bench_planned_f64(b, 251); } #[bench] fn wasm_simd_planned64_prime_0257(b: &mut Bencher) { bench_planned_f64(b, 257); } #[bench] fn wasm_simd_planned64_prime_2017(b: &mut Bencher) { bench_planned_f64(b, 2017); } #[bench] fn wasm_simd_planned64_prime_2879(b: &mut Bencher) { bench_planned_f64(b, 2879); } #[bench] fn wasm_simd_planned64_prime_65521(b: &mut Bencher) { bench_planned_f64(b, 65521); } #[bench] fn wasm_simd_planned64_prime_746497(b: &mut Bencher) { bench_planned_f64(b, 746497); } // small mixed composites #[bench] fn wasm_simd_planned32_composite_000018(b: &mut Bencher) { bench_planned_f32(b, 00018); } #[bench] fn wasm_simd_planned32_composite_000360(b: &mut Bencher) { bench_planned_f32(b, 00360); } #[bench] fn wasm_simd_planned32_composite_001200(b: &mut Bencher) { bench_planned_f32(b, 01200); } #[bench] fn wasm_simd_planned32_composite_044100(b: &mut Bencher) { bench_planned_f32(b, 44100); } #[bench] fn wasm_simd_planned32_composite_048000(b: &mut Bencher) { bench_planned_f32(b, 48000); } #[bench] fn wasm_simd_planned32_composite_046656(b: &mut Bencher) { bench_planned_f32(b, 46656); } #[bench] fn wasm_simd_planned64_composite_000018(b: &mut Bencher) { bench_planned_f64(b, 00018); } #[bench] fn wasm_simd_planned64_composite_000360(b: &mut Bencher) { bench_planned_f64(b, 00360); } #[bench] fn wasm_simd_planned64_composite_001200(b: &mut Bencher) { bench_planned_f64(b, 01200); } #[bench] fn wasm_simd_planned64_composite_044100(b: &mut Bencher) { bench_planned_f64(b, 44100); } #[bench] fn wasm_simd_planned64_composite_048000(b: &mut Bencher) { bench_planned_f64(b, 48000); } #[bench] fn wasm_simd_planned64_composite_046656(b: &mut Bencher) { bench_planned_f64(b, 46656); }