linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Ene
To: peterz@infradead.org, mingo@redhat.com, acme@kernel.org,
	namhyung@kernel.org, mark.rutland@arm.com,
	alexander.shishkin@linux.intel.com, jolsa@kernel.org,
	irogers@google.com, adrian.hunter@intel.com,
	kan.liang@linux.intel.com, linux-perf-users@vger.kernel.org,
	linux-kernel@vger.kernel.org
Cc: vinicius.gomes@intel.com, stefan.ene@intel.com, stef_an_ene@outlook.com
Subject: [RFC v1 3/3] C and Rust support for perf script
Date: Thu, 19 Sep 2024 14:51:04 -0700	[thread overview]
Message-ID: <20240919215107.2263552-5-stefan.ene@intel.com> (raw)
In-Reply-To: <20240919215107.2263552-2-stefan.ene@intel.com>

From: Stefan Ene <stefan.ene@intel.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


  parent reply	other threads:[~2024-09-19 21:51 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-19 21:51 [RFC v1 0/3] C and Rust support for perf script Stefan
2024-09-19 21:51 ` [RFC v1 1/3] " Stefan
2024-09-19 21:51 ` [RFC v1 2/3] " Stefan
2024-09-19 21:51 ` Stefan [this message]
2024-09-26  0:03 ` [RFC v1 0/3] " Namhyung Kim

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=20240919215107.2263552-5-stefan.ene@intel.com \
    --to=peterz@infradead.org \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=irogers@google.com \
    --cc=jolsa@kernel.org \
    --cc=kan.liang@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=stef_an_ene@outlook.com \
    --cc=stefan.ene@intel.com \
    --cc=vinicius.gomes@intel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).