-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add C API for GuestProfiler #7854
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
alexcrichton
merged 7 commits into
bytecodealliance:main
from
Milek7:guestprofiler-c-api
Feb 5, 2024
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
f2a9be1
Add C API for GuestProfiler
Milek7 c03f99a
GuestProfiler C API: remove unsafe and add docs
Milek7 5564ffb
Fix clang-format complaints
Milek7 ff34bf3
rename to wasmtime_guestprofiler_t for consistency, change to passing…
Milek7 6e3ddd9
rustfmt
Milek7 54e862b
out is marked "own" too
Milek7 87d5e01
gate on profiling feature
Milek7 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| /** | ||
| * \file wasmtime/profiling.h | ||
| * | ||
| * \brief API for Wasmtime guest profiler | ||
| */ | ||
|
|
||
| #ifndef WASMTIME_PROFILING_H | ||
| #define WASMTIME_PROFILING_H | ||
|
|
||
| #include <wasm.h> | ||
| #include <wasmtime/error.h> | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /** | ||
| * \brief Collects basic profiling data for a single WebAssembly guest. | ||
| * | ||
| * To use this, you’ll need to arrange to call #wasmtime_guestprofiler_sample at | ||
| * regular intervals while the guest is on the stack. The most straightforward | ||
| * way to do that is to call it from a callback registered with | ||
| * #wasmtime_store_epoch_deadline_callback. | ||
| * | ||
| * For more information see the Rust documentation at: | ||
| * https://docs.wasmtime.dev/api/wasmtime/struct.GuestProfiler.html | ||
| */ | ||
| typedef struct wasmtime_guestprofiler wasmtime_guestprofiler_t; | ||
|
|
||
| /** | ||
| * \brief Deletes profiler without finishing it. | ||
| * | ||
| * \param guestprofiler profiler that is being deleted | ||
| */ | ||
| WASM_API_EXTERN void wasmtime_guestprofiler_delete( | ||
| /* own */ wasmtime_guestprofiler_t *guestprofiler); | ||
|
|
||
| /** | ||
| * \typedef wasmtime_guestprofiler_modules_t | ||
| * \brief Alias to #wasmtime_guestprofiler_modules | ||
| * | ||
| * \struct #wasmtime_guestprofiler_modules | ||
| * \brief Tuple of name and module for passing into #wasmtime_guestprofiler_new. | ||
| */ | ||
| typedef struct wasmtime_guestprofiler_modules { | ||
| const wasm_name_t *name; //!< Name recorded in the profile. | ||
| const wasmtime_module_t | ||
| *mod; //!< Module that is being allowed to appear in captured stack trace. | ||
|
Milek7 marked this conversation as resolved.
|
||
| } wasmtime_guestprofiler_modules_t; | ||
|
|
||
| /** | ||
| * \brief Begin profiling a new guest. | ||
| * | ||
| * \param module_name name recorded in the profile | ||
| * \param interval_nanos intended sampling interval in nanoseconds recorded in | ||
| * the profile | ||
| * \param modules modules and associated names that will appear in | ||
| * captured stack traces, pointer to the first element | ||
| * \param modules_len count of elements in `modules` | ||
| * | ||
| * \return Created profiler that is owned by the caller. | ||
| * | ||
| * This function does not take ownership of the arguments. | ||
| * | ||
| * For more information see the Rust documentation at: | ||
| * https://docs.wasmtime.dev/api/wasmtime/struct.GuestProfiler.html#method.new | ||
| */ | ||
| WASM_API_EXTERN /* own */ wasmtime_guestprofiler_t *wasmtime_guestprofiler_new( | ||
| const wasm_name_t *module_name, uint64_t interval_nanos, | ||
| const wasmtime_guestprofiler_modules_t *modules, size_t modules_len); | ||
|
|
||
| /** | ||
| * \brief Add a sample to the profile. | ||
| * | ||
| * \param guestprofiler the profiler the sample is being added to | ||
| * \param store store that is being used to collect the backtraces | ||
| * | ||
| * This function does not take ownership of the arguments. | ||
| * | ||
| * For more information see the Rust documentation at: | ||
| * https://docs.wasmtime.dev/api/wasmtime/struct.GuestProfiler.html#method.sample | ||
| */ | ||
| WASM_API_EXTERN void | ||
| wasmtime_guestprofiler_sample(wasmtime_guestprofiler_t *guestprofiler, | ||
| const wasmtime_store_t *store); | ||
|
|
||
| /** | ||
| * \brief Writes out the captured profile. | ||
| * | ||
| * \param guestprofiler the profiler which is being finished and deleted | ||
| * \param out pointer to where #wasm_byte_vec_t containing generated | ||
| * file will be written | ||
| * | ||
| * \return Returns #wasmtime_error_t owned by the caller in case of error, | ||
| * `NULL` otherwise. | ||
| * | ||
| * This function takes ownership of `guestprofiler`, even when error is | ||
| * returned. | ||
| * Only when returning without error `out` is filled with #wasm_byte_vec_t owned | ||
| * by the caller. | ||
| * | ||
| * For more information see the Rust documentation at: | ||
| * https://docs.wasmtime.dev/api/wasmtime/struct.GuestProfiler.html#method.finish | ||
| */ | ||
| WASM_API_EXTERN /* own */ wasmtime_error_t * | ||
| wasmtime_guestprofiler_finish(/* own */ wasmtime_guestprofiler_t *guestprofiler, | ||
| /* own */ wasm_byte_vec_t *out); | ||
|
|
||
| #ifdef __cplusplus | ||
| } // extern "C" | ||
| #endif | ||
|
|
||
| #endif // WASMTIME_PROFILING_H | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| use crate::{wasm_byte_vec_t, wasm_name_t, wasmtime_error_t, wasmtime_module_t, wasmtime_store_t}; | ||
| use std::slice; | ||
| use std::str::from_utf8; | ||
| use std::time::Duration; | ||
| use wasmtime::GuestProfiler; | ||
|
|
||
| pub struct wasmtime_guestprofiler_t { | ||
| guest_profiler: GuestProfiler, | ||
| } | ||
|
|
||
| wasmtime_c_api_macros::declare_own!(wasmtime_guestprofiler_t); | ||
|
|
||
| #[repr(C)] | ||
| pub struct wasmtime_guestprofiler_modules_t<'a> { | ||
| name: &'a wasm_name_t, | ||
| module: &'a wasmtime_module_t, | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub unsafe extern "C" fn wasmtime_guestprofiler_new( | ||
| module_name: &wasm_name_t, | ||
| interval_nanos: u64, | ||
| modules: *const wasmtime_guestprofiler_modules_t, | ||
| modules_len: usize, | ||
| ) -> Box<wasmtime_guestprofiler_t> { | ||
| let module_name = from_utf8(&module_name.as_slice()).expect("not valid utf-8"); | ||
| let list = slice::from_raw_parts(modules, modules_len) | ||
| .iter() | ||
| .map(|entry| { | ||
| ( | ||
| from_utf8(entry.name.as_slice()) | ||
| .expect("not valid utf-8") | ||
| .to_owned(), | ||
| entry.module.module.clone(), | ||
| ) | ||
| }) | ||
| .collect(); | ||
| Box::new(wasmtime_guestprofiler_t { | ||
| guest_profiler: GuestProfiler::new(module_name, Duration::from_nanos(interval_nanos), list), | ||
| }) | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub extern "C" fn wasmtime_guestprofiler_sample( | ||
| guestprofiler: &mut wasmtime_guestprofiler_t, | ||
| store: &wasmtime_store_t, | ||
| ) { | ||
| guestprofiler.guest_profiler.sample(&store.store); | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub extern "C" fn wasmtime_guestprofiler_finish( | ||
| guestprofiler: Box<wasmtime_guestprofiler_t>, | ||
| out: &mut wasm_byte_vec_t, | ||
| ) -> Option<Box<wasmtime_error_t>> { | ||
| let mut buf = vec![]; | ||
| match guestprofiler.guest_profiler.finish(&mut buf) { | ||
| Ok(()) => { | ||
| out.set_buffer(buf); | ||
| None | ||
| } | ||
| Err(e) => Some(Box::new(e.into())), | ||
| } | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.