[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240919215107.2263552-5-stefan.ene@intel.com>
Date: Thu, 19 Sep 2024 14:51:04 -0700
From: Stefan@....codeaurora.org, Ene@....codeaurora.org
To: peterz@...radead.org,
mingo@...hat.com,
acme@...nel.org,
namhyung@...nel.org,
mark.rutland@....com,
alexander.shishkin@...ux.intel.com,
jolsa@...nel.org,
irogers@...gle.com,
adrian.hunter@...el.com,
kan.liang@...ux.intel.com,
linux-perf-users@...r.kernel.org,
linux-kernel@...r.kernel.org
Cc: vinicius.gomes@...el.com,
stefan.ene@...el.com,
stef_an_ene@...look.com
Subject: [RFC v1 3/3] C and Rust support for perf script
From: Stefan Ene <stefan.ene@...el.com>
[PATCH 3/3] added the Rust sample script
---
tools/perf/new_script_templates/README | 61 +++++++++++--
tools/perf/new_script_templates/lib.rs | 108 +++++++++++++++++++++++
tools/perf/new_script_templates/script.c | 6 ++
tools/perf/util/new_script_rs_lib.h | 35 ++++++++
4 files changed, 204 insertions(+), 6 deletions(-)
create mode 100644 tools/perf/new_script_templates/lib.rs
create mode 100644 tools/perf/util/new_script_rs_lib.h
diff --git a/tools/perf/new_script_templates/README b/tools/perf/new_script_templates/README
index c2a55a65d444..f16a9759d37e 100644
--- a/tools/perf/new_script_templates/README
+++ b/tools/perf/new_script_templates/README
@@ -2,15 +2,64 @@ Linux kernel additions for C and Rust script support inside the perf-script tool
Steps to use new feature:
- First, use the provided update_perf_tools.sh script to make sure your perf toolset is up to date with the latest implementation:
- $ bash update_perf_tools.sh
+ First, use run the following lines to make sure your perf toolset is up to date with the latest implementation:
+ $ cd ./tools/perf/
+ $ make
+ $ sudo cp perf /usr/bin
+ $ perf --version
+ Now, you can make use of our new features!
+
a) For C scripts:
- 1. Use the default C template test.c to write your own custom perf event processing
+ 1. Use the default C template in tools/perf/new_script_templates/script.c to write your own custom perf event processing
2. Compile the C script into a dynamic library using the following two commands:
- $ gcc -c -I ~/include -fpic new_script_templates/script.c
- $ gcc -shared -o test.so new_script_templates/script.o
+ $ gcc -c -I ~/include -fpic script.c
+ $ gcc -shared -o script.so script.o
3. Call the new perf script option to use the newly created .so file using the command:
- $ sudo perf script --new_script new_script_templates/script.so
\ No newline at end of file
+ $ sudo perf script --new_script script.so
+
+
+ b) For Rust scripts:
+ 1. Create a new Rust project using Cargo:
+ $ cargo new rslib_script --lib
+ $ cd rslib_script
+
+ 2. In the Cargo.toml file, specify the crate type as a dynamic library as follows:
+ [lib]
+ crate-type = ["cdylib"]
+
+ 3. Use the default Rust template in tools/perf/new_script_templates/lib.rs to write your own custom perf event processing, and store it into src/lib.rs inside of the Rust project folder.
+
+ 4. Compile the Rust project using Cargo:
+ $ cargo build --release
+
+ 5. Call the new perf script option to use the newly created /target/release/librslib.so within the Rust project using the followig command:
+ $ sudo perf script --new_script rslib/target/release/librslib.so
+
+Enjoy using the new scripting languages for an added bonus of usability and performance over the existent Python and Perl options in the upstream kernel code.
+
+
+<!-- ============================= -->
+
+This section contains some initial benchmark results on the Intel Lab machine using the perf script tools on a 4026869-byte perf.data file.
+
+Process ----- Time
+
+> Perf tool vanilla:
+perf script raw: 1.425s
+perf script names: 0.915s
+perf script Python: 1.334s
+perf script Perl: 2.210s
+
+
+> Pre-optimizations:
+new_script raw C: 0.284s
+new_script raw Rust: 0.607s
+
+> Post-optimizations:
+new_script raw C batch=1MB: 0.306s
+new_script raw C batch=2MB: 0.301s
+new_script raw C batch=4MB: 0.296s
+new_script raw Rust batch=1MB: 0.262s
\ No newline at end of file
diff --git a/tools/perf/new_script_templates/lib.rs b/tools/perf/new_script_templates/lib.rs
new file mode 100644
index 000000000000..1249d9e9099b
--- /dev/null
+++ b/tools/perf/new_script_templates/lib.rs
@@ -0,0 +1,108 @@
+// Stefan Ene's code, under Intel - Linux Kernel Team
+/*
+ * code for new perf script custom C script template
+ *
+ */
+
+ use std::os::raw::{c_char, c_int, c_void};
+ use std::slice;
+ use std::fmt::Write;
+
+ // =================== Needed stuff, DO NOT CHANGE ===================
+
+ #[repr(C)]
+ struct NewScript {
+ file: *mut c_char,
+ handle: *mut c_void,
+
+ begin: extern "C" fn(*mut c_void, *mut c_void),
+ end: extern "C" fn(*mut c_void, *mut c_void),
+
+ process_file_header: extern "C" fn(*mut c_void, *mut c_void) -> c_int,
+ process_event_header: extern "C" fn(*mut c_void, *mut c_void) -> c_int,
+ process_event_raw_data: extern "C" fn(*mut c_void, c_int, *mut c_void) -> c_int,
+ }
+
+ #[repr(C)]
+ struct ProcessedFileHeader {
+ size: u64,
+ data_size: u64,
+ data_offset: u64,
+ }
+
+ #[repr(C)]
+ struct ProcessedEventHeader {
+ event_type: u32,
+ misc: u16,
+ size: u16,
+ }
+
+ // =================== Editable funtions begin ===================
+
+ #[no_mangle]
+ pub extern "C" fn print_begin(_data: *mut c_void, _ctx: *mut c_void) {
+ println!(">> in trace_begin with Rust");
+ }
+
+ #[no_mangle]
+ pub extern "C" fn process_file_header(data: *mut c_void, _ctx: *mut c_void) -> c_int {
+ if data.is_null() {
+ println!("> Error dynamically processing file header");
+ return -1;
+ }
+
+ let fh = unsafe { &*(data as *const ProcessedFileHeader) };
+
+ println!("\nFile header: size={:x}, data.size={}, data.offset={}", fh.size, fh.data_size, fh.data_offset);
+
+ 0
+ }
+
+ #[no_mangle]
+ pub extern "C" fn process_event_header(data: *mut c_void, _ctx: *mut c_void) -> c_int {
+ if data.is_null() {
+ println!("> Error dynamically processing event header");
+ return -1;
+ }
+
+ let evh = unsafe { &*(data as *const ProcessedEventHeader) };
+
+ println!("\nRS Event header: size={}, type={}, misc={}", evh.size, evh.event_type, evh.misc);
+
+ 0
+ }
+
+ #[no_mangle]
+ pub extern "C" fn process_event_raw_data(data: *mut c_void, size: c_int, _ctx: *mut c_void) -> c_int {
+ let byte_data = unsafe { slice::from_raw_parts(data as *const u8, size as usize) };
+ let mut output = String::new();
+
+ for (i, &byte) in byte_data.iter().enumerate() {
+ if i % 16 == 0 {
+ output.push('\n');
+ }
+ write!(&mut output, "{:02x} ", byte).unwrap();
+ }
+
+ println!("{}", output);
+ 0
+ }
+
+ #[no_mangle]
+ pub extern "C" fn print_end(_data: *mut c_void, _ctx: *mut c_void) {
+ println!("\n>> in trace_end");
+ }
+
+ // =================== Needed stuff begin, DO NOT CHANGE ===================
+
+ #[no_mangle]
+ pub extern "C" fn initialize_new_script(s: *mut NewScript) {
+ if !s.is_null() {
+ let script = unsafe { &mut *s };
+ script.begin = print_begin;
+ script.end = print_end;
+ script.process_file_header = process_file_header;
+ script.process_event_header = process_event_header;
+ script.process_event_raw_data = process_event_raw_data;
+ }
+ }
\ No newline at end of file
diff --git a/tools/perf/new_script_templates/script.c b/tools/perf/new_script_templates/script.c
index e4942ba689db..787f67424d5e 100644
--- a/tools/perf/new_script_templates/script.c
+++ b/tools/perf/new_script_templates/script.c
@@ -1,3 +1,9 @@
+// Stefan Ene's code, under Intel - Linux Kernel Team
+/*
+ * code for new perf script custom C script template
+ *
+ */
+
#include <stdlib.h>
#include <stdio.h>
diff --git a/tools/perf/util/new_script_rs_lib.h b/tools/perf/util/new_script_rs_lib.h
new file mode 100644
index 000000000000..4a8d6f71b122
--- /dev/null
+++ b/tools/perf/util/new_script_rs_lib.h
@@ -0,0 +1,35 @@
+// Stefan Ene's code, under Intel - Linux Kernel Team
+/*
+ * new_script_lib_rs.h: header file for new_script Rust FFI
+ *
+ */
+
+#ifndef NEW_SCRIPT_LIB_RS_H
+#define NEW_SCRIPT_LIB_RS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+// Match the struct definitions with the Rust code
+struct NewScript {
+ char *file;
+ void *handle;
+
+ void (*begin)(void *data, void *ctx);
+ void (*end)(void *data, void *ctx);
+
+ int (*process_file_header)(void *data, void *ctx);
+ int (*process_event_header)(void *data, void *ctx);
+ int (*process_event_raw_data)(void *data, const int size, void *ctx);
+};
+
+void initialize_new_script(struct NewScript* s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NEW_SCRIPT_LIB_RS_H
\ No newline at end of file
--
2.46.0
Powered by blists - more mailing lists