1 // SPDX-License-Identifier: GPL-2.0 2 //! Benchmark for find_bit-like methods in Bitmap Rust API. 3 4 use kernel::alloc::flags::GFP_KERNEL; 5 use kernel::bindings; 6 use kernel::bitmap::BitmapVec; 7 use kernel::error::{code, Result}; 8 use kernel::prelude::module; 9 use kernel::time::{Instant, Monotonic}; 10 use kernel::ThisModule; 11 use kernel::{pr_cont, pr_err}; 12 13 const BITMAP_LEN: usize = 4096 * 8 * 10; 14 // Reciprocal of the fraction of bits that are set in sparse bitmap. 15 const SPARSENESS: usize = 500; 16 17 /// Test module that benchmarks performance of traversing bitmaps. 18 struct Benchmark(); 19 20 fn test_next_bit(bitmap: &BitmapVec) { 21 let time = Instant::<Monotonic>::now(); 22 let mut cnt = 0; 23 let mut i = 0; 24 25 while let Some(index) = bitmap.next_bit(i) { 26 cnt += 1; 27 i = index + 1; 28 // CONFIG_RUST_BITMAP_HARDENED enforces strict bounds. 29 if i == BITMAP_LEN { 30 break; 31 } 32 } 33 34 let delta = time.elapsed(); 35 pr_cont!( 36 "\nnext_bit: {:18} ns, {:6} iterations", 37 delta.as_nanos(), 38 cnt 39 ); 40 } 41 42 fn test_next_zero_bit(bitmap: &BitmapVec) { 43 let time = Instant::<Monotonic>::now(); 44 let mut cnt = 0; 45 let mut i = 0; 46 47 while let Some(index) = bitmap.next_zero_bit(i) { 48 cnt += 1; 49 i = index + 1; 50 // CONFIG_RUST_BITMAP_HARDENED enforces strict bounds. 51 if i == BITMAP_LEN { 52 break; 53 } 54 } 55 56 let delta = time.elapsed(); 57 pr_cont!( 58 "\nnext_zero_bit: {:18} ns, {:6} iterations", 59 delta.as_nanos(), 60 cnt 61 ); 62 } 63 64 fn find_bit_test() { 65 pr_err!("Benchmark"); 66 pr_cont!("\nStart testing find_bit() Rust with random-filled bitmap"); 67 68 let mut bitmap = BitmapVec::new(BITMAP_LEN, GFP_KERNEL).expect("alloc bitmap failed"); 69 bitmap.fill_random(); 70 71 test_next_bit(&bitmap); 72 test_next_zero_bit(&bitmap); 73 74 pr_cont!("\nStart testing find_bit() Rust with sparse bitmap"); 75 76 let mut bitmap = BitmapVec::new(BITMAP_LEN, GFP_KERNEL).expect("alloc sparse bitmap failed"); 77 let nbits = BITMAP_LEN / SPARSENESS; 78 for _i in 0..nbits { 79 // SAFETY: __get_random_u32_below is safe to call with any u32 argument. 80 let bit = 81 unsafe { bindings::__get_random_u32_below(BITMAP_LEN.try_into().unwrap()) as usize }; 82 bitmap.set_bit(bit); 83 } 84 85 test_next_bit(&bitmap); 86 test_next_zero_bit(&bitmap); 87 pr_cont!("\n"); 88 } 89 90 impl kernel::Module for Benchmark { 91 fn init(_module: &'static ThisModule) -> Result<Self> { 92 find_bit_test(); 93 // Return error so test module can be inserted again without rmmod. 94 Err(code::EINVAL) 95 } 96 } 97 98 module! { 99 type: Benchmark, 100 name: "find_bit_benchmark_rust", 101 authors: ["Burak Emir <bqe@google.com>"], 102 description: "Module with benchmark for bitmap Rust API", 103 license: "GPL v2", 104 } 105