at master 2.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2//! Benchmark for find_bit-like methods in Bitmap Rust API. 3 4use kernel::alloc::flags::GFP_KERNEL; 5use kernel::bindings; 6use kernel::bitmap::BitmapVec; 7use kernel::error::{code, Result}; 8use kernel::prelude::module; 9use kernel::time::{Instant, Monotonic}; 10use kernel::ThisModule; 11use kernel::{pr_cont, pr_err}; 12 13const BITMAP_LEN: usize = 4096 * 8 * 10; 14// Reciprocal of the fraction of bits that are set in sparse bitmap. 15const SPARSENESS: usize = 500; 16 17/// Test module that benchmarks performance of traversing bitmaps. 18struct Benchmark(); 19 20fn 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 42fn 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 64fn 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 90impl 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 98module! { 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}