From: Burak Emir <bqe@google.com>
To: Yury Norov <yury.norov@gmail.com>, Kees Cook <kees@kernel.org>
Cc: "Burak Emir" <bqe@google.com>,
"Rasmus Villemoes" <linux@rasmusvillemoes.dk>,
"Viresh Kumar" <viresh.kumar@linaro.org>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Gustavo A . R . Silva" <gustavoars@kernel.org>,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-hardening@vger.kernel.org
Subject: [PATCH v9 4/5] rust: add find_bit_benchmark_rust module.
Date: Mon, 26 May 2025 15:01:33 +0000 [thread overview]
Message-ID: <20250526150141.3407433-5-bqe@google.com> (raw)
In-Reply-To: <20250526150141.3407433-1-bqe@google.com>
Microbenchmark protected by a config FIND_BIT_BENCHMARK_RUST,
following `find_bit_benchmark.c` but testing the Rust Bitmap API.
We add a fill_random() method protected by the config in order to
maintain the abstraction.
Suggested-by: Alice Ryhl <aliceryhl@google.com>
Suggested-by: Yury Norov <yury.norov@gmail.com>
Signed-off-by: Burak Emir <bqe@google.com>
---
MAINTAINERS | 1 +
lib/Kconfig.debug | 13 +++++
lib/Makefile | 1 +
lib/find_bit_benchmark_rust.rs | 94 +++++++++++++++++++++++++++++++++
rust/bindings/bindings_helper.h | 1 +
rust/kernel/bitmap.rs | 14 +++++
6 files changed, 124 insertions(+)
create mode 100644 lib/find_bit_benchmark_rust.rs
diff --git a/MAINTAINERS b/MAINTAINERS
index 565eaa015d9e..943d85ed1876 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4132,6 +4132,7 @@ M: Alice Ryhl <aliceryhl@google.com>
M: Burak Emir <bqe@google.com>
R: Yury Norov <yury.norov@gmail.com>
S: Maintained
+F: lib/find_bit_benchmark_rust.rs
F: rust/kernel/bitmap.rs
BITOPS API
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index f9051ab610d5..37a07559243e 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -2605,6 +2605,19 @@ config FIND_BIT_BENCHMARK
If unsure, say N.
+config FIND_BIT_BENCHMARK_RUST
+ tristate "Test find_bit functions in Rust"
+ help
+ This builds the "find_bit_benchmark_rust" module. It is a micro
+ benchmark that measures the performance of Rust functions that
+ correspond to the find_*_bit() operations in C. It follows the
+ FIND_BIT_BENCHMARK closely but will in general not yield same
+ numbers due to extra bounds checks and overhead of foreign
+ function calls.
+
+ If unsure, say N.
+
+
config TEST_FIRMWARE
tristate "Test firmware loading via userspace interface"
depends on FW_LOADER
diff --git a/lib/Makefile b/lib/Makefile
index f07b24ce1b3f..99e49a8f5bf8 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -62,6 +62,7 @@ obj-y += hexdump.o
obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o
obj-y += kstrtox.o
obj-$(CONFIG_FIND_BIT_BENCHMARK) += find_bit_benchmark.o
+obj-$(CONFIG_FIND_BIT_BENCHMARK_RUST) += find_bit_benchmark_rust.o
obj-$(CONFIG_TEST_BPF) += test_bpf.o
test_dhry-objs := dhry_1.o dhry_2.o dhry_run.o
obj-$(CONFIG_TEST_DHRY) += test_dhry.o
diff --git a/lib/find_bit_benchmark_rust.rs b/lib/find_bit_benchmark_rust.rs
new file mode 100644
index 000000000000..4966bfa497f1
--- /dev/null
+++ b/lib/find_bit_benchmark_rust.rs
@@ -0,0 +1,94 @@
+// 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::Bitmap;
+use kernel::error::{code, Result};
+use kernel::pr_err;
+use kernel::prelude::module;
+use kernel::time::Ktime;
+use kernel::ThisModule;
+
+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 FindBitBenchmarkModule();
+
+fn test_next_bit(bitmap: &Bitmap) {
+ let mut time = Ktime::ktime_get();
+ let mut cnt = 0;
+ let mut i = 0;
+
+ while let Some(index) = bitmap.next_bit(i) {
+ cnt += 1;
+ i = index + 1;
+ }
+
+ time = Ktime::ktime_get() - time;
+ pr_err!(
+ "next_bit: {:18} ns, {:6} iterations\n",
+ time.to_ns(),
+ cnt
+ );
+}
+
+fn test_next_zero_bit(bitmap: &Bitmap) {
+ let mut time = Ktime::ktime_get();
+ let mut cnt = 0;
+ let mut i = 0;
+
+ while let Some(index) = bitmap.next_zero_bit(i) {
+ cnt += 1;
+ i = index + 1;
+ }
+
+ time = Ktime::ktime_get() - time;
+ pr_err!(
+ "next_zero_bit: {:18} ns, {:6} iterations\n",
+ time.to_ns(),
+ cnt
+ );
+}
+
+fn find_bit_test() {
+ pr_err!("Start testing find_bit() Rust with random-filled bitmap\n");
+
+ let mut bitmap = Bitmap::new(BITMAP_LEN, GFP_KERNEL).expect("alloc bitmap failed");
+ bitmap.fill_random();
+
+ test_next_bit(&bitmap);
+ test_next_zero_bit(&bitmap);
+
+ pr_err!("Start testing find_bit() Rust with sparse bitmap\n");
+
+ let mut bitmap = Bitmap::new(BITMAP_LEN, GFP_KERNEL).expect("alloc sparse bitmap failed");
+ let nbits = BITMAP_LEN / SPARSENESS;
+ for _i in 0..nbits {
+ // SAFETY: BITMAP_LEN fits in 32 bits.
+ let bit: usize =
+ unsafe { bindings::__get_random_u32_below(BITMAP_LEN.try_into().unwrap()) as _ };
+ bitmap.set_bit(bit);
+ }
+
+ test_next_bit(&bitmap);
+ test_next_zero_bit(&bitmap);
+}
+
+impl kernel::Module for FindBitBenchmarkModule {
+ 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: FindBitBenchmarkModule,
+ name: "find_bit_benchmark_rust_module",
+ authors: ["Burak Emir <bqe@google.com>"],
+ description: "Module with benchmark for bitmap Rust API",
+ license: "GPL v2",
+}
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index b6bf3b039c1b..f6ca7f1dd08b 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -31,6 +31,7 @@
#include <linux/platform_device.h>
#include <linux/poll.h>
#include <linux/property.h>
+#include <linux/random.h>
#include <linux/refcount.h>
#include <linux/sched.h>
#include <linux/security.h>
diff --git a/rust/kernel/bitmap.rs b/rust/kernel/bitmap.rs
index a6edd4889518..fa5fef0b6acd 100644
--- a/rust/kernel/bitmap.rs
+++ b/rust/kernel/bitmap.rs
@@ -232,6 +232,20 @@ pub fn new(nbits: usize, flags: Flags) -> Result<Self, AllocError> {
pub fn len(&self) -> usize {
self.nbits
}
+
+ /// Fills this `Bitmap` with random bits.
+ #[cfg(CONFIG_FIND_BIT_BENCHMARK_RUST)]
+ pub fn fill_random(&mut self) {
+ // SAFETY: `self.as_mut_ptr` points to either an array of the
+ // appropriate length or one usize.
+ unsafe {
+ bindings::get_random_bytes(
+ self.as_mut_ptr() as *mut ffi::c_void,
+ usize::div_ceil(self.nbits, bindings::BITS_PER_LONG as usize)
+ * bindings::BITS_PER_LONG as usize,
+ );
+ }
+ }
}
impl CBitmap {
--
2.49.0.1151.ga128411c76-goog
next prev parent reply other threads:[~2025-05-26 15:01 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-26 15:01 [PATCH v9 0/5] rust: adds Bitmap API, ID pool and bindings Burak Emir
2025-05-26 15:01 ` [PATCH v9 1/5] rust: add bindings for bitmap.h Burak Emir
2025-05-26 15:01 ` [PATCH v9 2/5] rust: add bindings for bitops.h Burak Emir
2025-05-27 16:38 ` Boqun Feng
2025-06-02 13:11 ` Burak Emir
2025-05-26 15:01 ` [PATCH v9 3/5] rust: add bitmap API Burak Emir
2025-05-27 16:35 ` Boqun Feng
2025-05-26 15:01 ` Burak Emir [this message]
2025-05-28 9:10 ` [PATCH v9 4/5] rust: add find_bit_benchmark_rust module kernel test robot
2025-05-26 15:01 ` [PATCH v9 5/5] rust: add dynamic ID pool abstraction for bitmap Burak Emir
2025-05-27 14:27 ` [PATCH v9 0/5] rust: adds Bitmap API, ID pool and bindings Yury Norov
2025-06-02 9:52 ` Burak Emir
2025-05-27 14:43 ` Yury Norov
2025-06-02 10:56 ` Burak Emir
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250526150141.3407433-5-bqe@google.com \
--to=bqe@google.com \
--cc=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=gary@garyguo.net \
--cc=gustavoars@kernel.org \
--cc=kees@kernel.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@rasmusvillemoes.dk \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
--cc=viresh.kumar@linaro.org \
--cc=yury.norov@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.