File: find_bit_benchmark_rust.rs

package info (click to toggle)
linux 6.18.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,742,780 kB
  • sloc: ansic: 26,780,494; asm: 272,079; sh: 148,752; python: 79,241; makefile: 57,741; perl: 36,527; xml: 19,542; cpp: 5,911; yacc: 4,939; lex: 2,950; awk: 1,607; sed: 30; ruby: 25
file content (104 lines) | stat: -rw-r--r-- 2,864 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// SPDX-License-Identifier: GPL-2.0
//! Benchmark for find_bit-like methods in Bitmap Rust API.

use kernel::alloc::flags::GFP_KERNEL;
use kernel::bindings;
use kernel::bitmap::BitmapVec;
use kernel::error::{code, Result};
use kernel::prelude::module;
use kernel::time::{Instant, Monotonic};
use kernel::ThisModule;
use kernel::{pr_cont, pr_err};

const BITMAP_LEN: usize = 4096 * 8 * 10;
// Reciprocal of the fraction of bits that are set in sparse bitmap.
const SPARSENESS: usize = 500;

/// Test module that benchmarks performance of traversing bitmaps.
struct Benchmark();

fn test_next_bit(bitmap: &BitmapVec) {
    let time = Instant::<Monotonic>::now();
    let mut cnt = 0;
    let mut i = 0;

    while let Some(index) = bitmap.next_bit(i) {
        cnt += 1;
        i = index + 1;
        // CONFIG_RUST_BITMAP_HARDENED enforces strict bounds.
        if i == BITMAP_LEN {
            break;
        }
    }

    let delta = time.elapsed();
    pr_cont!(
        "\nnext_bit:           {:18} ns, {:6} iterations",
        delta.as_nanos(),
        cnt
    );
}

fn test_next_zero_bit(bitmap: &BitmapVec) {
    let time = Instant::<Monotonic>::now();
    let mut cnt = 0;
    let mut i = 0;

    while let Some(index) = bitmap.next_zero_bit(i) {
        cnt += 1;
        i = index + 1;
        // CONFIG_RUST_BITMAP_HARDENED enforces strict bounds.
        if i == BITMAP_LEN {
            break;
        }
    }

    let delta = time.elapsed();
    pr_cont!(
        "\nnext_zero_bit:      {:18} ns, {:6} iterations",
        delta.as_nanos(),
        cnt
    );
}

fn find_bit_test() {
    pr_err!("Benchmark");
    pr_cont!("\nStart testing find_bit() Rust with random-filled bitmap");

    let mut bitmap = BitmapVec::new(BITMAP_LEN, GFP_KERNEL).expect("alloc bitmap failed");
    bitmap.fill_random();

    test_next_bit(&bitmap);
    test_next_zero_bit(&bitmap);

    pr_cont!("\nStart testing find_bit() Rust with sparse bitmap");

    let mut bitmap = BitmapVec::new(BITMAP_LEN, GFP_KERNEL).expect("alloc sparse bitmap failed");
    let nbits = BITMAP_LEN / SPARSENESS;
    for _i in 0..nbits {
        // SAFETY: __get_random_u32_below is safe to call with any u32 argument.
        let bit =
            unsafe { bindings::__get_random_u32_below(BITMAP_LEN.try_into().unwrap()) as usize };
        bitmap.set_bit(bit);
    }

    test_next_bit(&bitmap);
    test_next_zero_bit(&bitmap);
    pr_cont!("\n");
}

impl kernel::Module for Benchmark {
    fn init(_module: &'static ThisModule) -> Result<Self> {
        find_bit_test();
        // Return error so test module can be inserted again without rmmod.
        Err(code::EINVAL)
    }
}

module! {
    type: Benchmark,
    name: "find_bit_benchmark_rust",
    authors: ["Burak Emir <bqe@google.com>"],
    description: "Module with benchmark for bitmap Rust API",
    license: "GPL v2",
}