1 //! Adds support for profiling JIT-ed code using VTune. By default, VTune
2 //! support is built in to Wasmtime (configure with the `vtune` feature flag).
3 //! To enable it at runtime, use the `--profile=vtune` CLI flag.
4 //!
5 //! ### Profile
6 //!
7 //! ```ignore
8 //! vtune -run-pass-thru=--no-altstack -v -collect hotspots target/debug/wasmtime --profile=vtune test.wasm
9 //! ```
10 //!
11 //! Note: `vtune` is a command-line tool for VTune which must [be
12 //! installed](https://www.intel.com/content/www/us/en/developer/tools/oneapi/vtune-profiler.html#standalone)
13 //! for this to work.
14 
15 use crate::prelude::*;
16 use crate::profiling_agent::ProfilingAgent;
17 use ittapi::jit::MethodLoadBuilder;
18 use std::sync::Mutex;
19 
20 /// Interface for driving the ittapi for VTune support
21 struct VTuneAgent {
22     // Note that we use a mutex internally to serialize state updates since multiple threads may be
23     // sharing this agent.
24     state: Mutex<State>,
25 }
26 
27 /// Interface for driving vtune
28 #[derive(Default)]
29 struct State {
30     vtune: ittapi::jit::Jit,
31 }
32 
33 /// Initialize a VTuneAgent.
new() -> Result<Box<dyn ProfilingAgent>>34 pub fn new() -> Result<Box<dyn ProfilingAgent>> {
35     Ok(Box::new(VTuneAgent {
36         state: Mutex::new(State {
37             vtune: Default::default(),
38         }),
39     }))
40 }
41 
42 impl Drop for VTuneAgent {
drop(&mut self)43     fn drop(&mut self) {
44         self.state.lock().unwrap().event_shutdown();
45     }
46 }
47 
48 impl State {
49     /// Notify vtune about a newly tracked code region.
notify_code(&mut self, module_name: &str, method_name: &str, code: &[u8])50     fn notify_code(&mut self, module_name: &str, method_name: &str, code: &[u8]) {
51         self.vtune
52             .load_method(
53                 MethodLoadBuilder::new(method_name.to_owned(), code.as_ptr(), code.len())
54                     .class_file_name(module_name.to_owned())
55                     .source_file_name("<unknown wasm filename>".to_owned()),
56             )
57             .unwrap();
58     }
59 
60     /// Shutdown module
event_shutdown(&mut self)61     fn event_shutdown(&mut self) {
62         // Ignore if something went wrong.
63         let _ = self.vtune.shutdown();
64     }
65 }
66 
67 impl ProfilingAgent for VTuneAgent {
register_function(&self, name: &str, code: &[u8])68     fn register_function(&self, name: &str, code: &[u8]) {
69         self.state.lock().unwrap().register_function(name, code);
70     }
71 }
72 
73 impl State {
register_function(&mut self, name: &str, code: &[u8])74     fn register_function(&mut self, name: &str, code: &[u8]) {
75         self.notify_code("wasmtime", name, code);
76     }
77 }
78