Support vtune profiling of trampolines too (#3687)
* Provide helpers for demangling function names * Profile trampolines in vtune too * get rid of mapping * avoid code duplication with jitdump_linux * maintain previous default display name for wasm functions * no dash, grrr * Remove unused profiling error type
This commit is contained in:
@@ -9,10 +9,10 @@
|
||||
//! ### Profile
|
||||
//!
|
||||
//! ```ignore
|
||||
//! amplxe-cl -run-pass-thru=--no-altstack -v -collect hotspots target/debug/wasmtime --vtune test.wasm
|
||||
//! vtune -run-pass-thru=--no-altstack -v -collect hotspots target/debug/wasmtime --vtune test.wasm
|
||||
//! ```
|
||||
//!
|
||||
//! Note: `amplxe-cl` is a command-line tool for VTune which must [be
|
||||
//! Note: `vtune` is a command-line tool for VTune which must [be
|
||||
//! installed](https://www.intel.com/content/www/us/en/developer/tools/oneapi/vtune-profiler.html#standalone)
|
||||
//! for this to work.
|
||||
|
||||
@@ -20,10 +20,9 @@ use crate::{CompiledModule, ProfilingAgent};
|
||||
use anyhow::Result;
|
||||
use core::ptr;
|
||||
use ittapi_rs::*;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::CString;
|
||||
use std::sync::{atomic, Mutex};
|
||||
use wasmtime_environ::DefinedFuncIndex;
|
||||
use wasmtime_environ::EntityRef;
|
||||
|
||||
/// Interface for driving the ittapi for VTune support
|
||||
pub struct VTuneAgent {
|
||||
@@ -34,19 +33,13 @@ pub struct VTuneAgent {
|
||||
|
||||
/// Interface for driving vtune
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct State {
|
||||
/// Unique identifier for the jitted function
|
||||
method_id: HashMap<(usize, DefinedFuncIndex), u32>,
|
||||
}
|
||||
struct State;
|
||||
|
||||
impl VTuneAgent {
|
||||
/// Intialize a VTuneAgent and write out the header
|
||||
/// Initialize a VTuneAgent.
|
||||
pub fn new() -> Result<Self> {
|
||||
let state = State {
|
||||
method_id: HashMap::new(),
|
||||
};
|
||||
Ok(VTuneAgent {
|
||||
state: Mutex::new(state),
|
||||
state: Mutex::new(State),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -58,24 +51,15 @@ impl Drop for VTuneAgent {
|
||||
}
|
||||
|
||||
impl State {
|
||||
/// Return the unique method ID for use with the ittapi
|
||||
pub fn get_method_id(&mut self, module_id: usize, func_idx: DefinedFuncIndex) -> u32 {
|
||||
let method_id: u32;
|
||||
unsafe {
|
||||
method_id = iJIT_GetNewMethodID();
|
||||
}
|
||||
assert_eq!(
|
||||
self.method_id.insert((module_id, func_idx), method_id),
|
||||
None
|
||||
);
|
||||
method_id
|
||||
/// Return a method ID for use with the ittapi.
|
||||
fn get_method_id(&self) -> u32 {
|
||||
unsafe { iJIT_GetNewMethodID() }
|
||||
}
|
||||
|
||||
/// Load module
|
||||
pub fn event_load(
|
||||
/// Notify vtune about a newly tracked code region.
|
||||
fn event_load(
|
||||
&mut self,
|
||||
method_id: u32,
|
||||
filename: &str,
|
||||
module_name: &str,
|
||||
method_name: &str,
|
||||
addr: *const u8,
|
||||
@@ -94,13 +78,16 @@ impl State {
|
||||
class_file_name: CString::new(module_name)
|
||||
.expect("CString::new failed")
|
||||
.into_raw(),
|
||||
source_file_name: CString::new(filename)
|
||||
source_file_name: CString::new("<unknown wasm filename>")
|
||||
.expect("CString::new failed")
|
||||
.into_raw(),
|
||||
};
|
||||
let jmethod_ptr = &mut jmethod as *mut _ as *mut _;
|
||||
unsafe {
|
||||
println!("EventLoad: NotifyEvent Called {}", method_id);
|
||||
log::trace!(
|
||||
"NotifyEvent: method load (single method with id {})",
|
||||
method_id
|
||||
);
|
||||
let _ret = iJIT_NotifyEvent(
|
||||
iJIT_jvm_event_iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
|
||||
jmethod_ptr as *mut ::std::os::raw::c_void,
|
||||
@@ -111,7 +98,7 @@ impl State {
|
||||
/// Shutdown module
|
||||
fn event_shutdown(&mut self) -> () {
|
||||
unsafe {
|
||||
println!("Drop was called!!!!!!\n");
|
||||
log::trace!("NotifyEvent shutdown (whole module)");
|
||||
let _ret = iJIT_NotifyEvent(iJIT_jvm_event_iJVM_EVENT_TYPE_SHUTDOWN, ptr::null_mut());
|
||||
}
|
||||
}
|
||||
@@ -121,8 +108,11 @@ impl ProfilingAgent for VTuneAgent {
|
||||
fn module_load(&self, module: &CompiledModule, dbg_image: Option<&[u8]>) {
|
||||
self.state.lock().unwrap().module_load(module, dbg_image);
|
||||
}
|
||||
fn trampoline_load(&self, _file: &object::File<'_>) {
|
||||
// TODO: needs an implementation
|
||||
fn load_single_trampoline(&self, name: &str, addr: *const u8, size: usize, pid: u32, tid: u32) {
|
||||
self.state
|
||||
.lock()
|
||||
.unwrap()
|
||||
.load_single_trampoline(name, addr, size, pid, tid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,29 +122,52 @@ impl State {
|
||||
static MODULE_ID: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
|
||||
let global_module_id = MODULE_ID.fetch_add(1, atomic::Ordering::SeqCst);
|
||||
|
||||
let module_name = module
|
||||
.module()
|
||||
.name
|
||||
.as_ref()
|
||||
.cloned()
|
||||
.unwrap_or_else(|| format!("wasm_module_{}", global_module_id));
|
||||
|
||||
for (idx, func) in module.finished_functions() {
|
||||
let (addr, len) = unsafe { ((*func).as_ptr() as *const u8, (*func).len()) };
|
||||
let default_filename = "wasm_file";
|
||||
let default_module_name = String::from("wasm_module");
|
||||
let module_name = module
|
||||
.module()
|
||||
.name
|
||||
.as_ref()
|
||||
.unwrap_or(&default_module_name);
|
||||
let method_name = super::debug_name(module.module(), idx);
|
||||
let method_id = self.get_method_id(global_module_id, idx);
|
||||
println!(
|
||||
"Event Load: ({}) {:?}::{:?} Addr:{:?}\n",
|
||||
method_id, module_name, method_name, addr
|
||||
);
|
||||
self.event_load(
|
||||
let method_id = self.get_method_id();
|
||||
log::trace!(
|
||||
"new function ({}) {:?}::{:?} @ {:?}\n",
|
||||
method_id,
|
||||
default_filename,
|
||||
module_name,
|
||||
&method_name,
|
||||
addr,
|
||||
len,
|
||||
method_name,
|
||||
addr
|
||||
);
|
||||
self.event_load(method_id, &module_name, &method_name, addr, len);
|
||||
}
|
||||
|
||||
// Note: these are the trampolines into exported functions.
|
||||
for (idx, func, len) in module.trampolines() {
|
||||
let idx = idx.index();
|
||||
let (addr, len) = (func as usize as *const u8, len);
|
||||
let method_name = format!("wasm::trampoline[{}]", idx,);
|
||||
let method_id = self.get_method_id();
|
||||
log::trace!(
|
||||
"new trampoline ({}) for exported signature {} @ {:?}\n",
|
||||
method_id,
|
||||
idx,
|
||||
addr
|
||||
);
|
||||
self.event_load(method_id, &module_name, &method_name, addr, len);
|
||||
}
|
||||
}
|
||||
|
||||
fn load_single_trampoline(
|
||||
&mut self,
|
||||
name: &str,
|
||||
addr: *const u8,
|
||||
size: usize,
|
||||
_pid: u32,
|
||||
_tid: u32,
|
||||
) {
|
||||
let method_id = self.get_method_id();
|
||||
self.event_load(method_id, "wasm trampoline for Func::new", name, addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user