1# Using `perf` on Linux 2 3One profiler supported by Wasmtime is the [`perf` 4profiler](https://perf.wiki.kernel.org/index.php/Main_Page) for Linux. This is 5an extremely powerful profiler with lots of documentation on the web, but for 6the rest of this section we'll assume you're running on Linux and already have 7`perf` installed. 8 9Profiling support with `perf` uses the "jitdump" support in the `perf` CLI. This 10requires runtime support from Wasmtime itself, so you will need to manually 11change a few things to enable profiling support in your application. First 12you'll want to make sure that Wasmtime is compiled with the `jitdump` Cargo 13feature (which is enabled by default). Otherwise enabling runtime support 14depends on how you're using Wasmtime: 15 16* **Rust API** - you'll want to call the [`Config::profiler`] method with 17 `ProfilingStrategy::JitDump` to enable profiling of your wasm modules. 18 19* **C API** - you'll want to call the `wasmtime_config_profiler_set` API with a 20 `WASMTIME_PROFILING_STRATEGY_JITDUMP` value. 21 22* **Command Line** - you'll want to pass the `--jitdump` flag on the command 23 line. 24 25Once jitdump support is enabled, you'll use `perf record` like usual to record 26your application's performance. You'll need to also be sure to pass the 27`--clockid mono` or `-k mono` flag to `perf record`. 28 29For example if you're using the CLI, you'll execute: 30 31```sh 32$ perf record -k mono wasmtime --jitdump foo.wasm 33``` 34 35This will create a `perf.data` file as per usual, but it will *also* create a 36`jit-XXXX.dump` file. This extra `*.dump` file is the jitdump file which is 37specified by `perf` and Wasmtime generates at runtime. 38 39The next thing you need to do is to merge the `*.dump` file into the 40`perf.data` file, which you can do with the `perf inject` command: 41 42```sh 43$ perf inject --jit --input perf.data --output perf.jit.data 44``` 45 46This will read `perf.data`, automatically pick up the `*.dump` file that's 47correct, and then create `perf.jit.data` which merges all the JIT information 48together. This should also create a lot of `jitted-XXXX-N.so` files in the 49current directory which are ELF images for all the JIT functions that were 50created by Wasmtime. 51 52After that you can explore the `perf.jit.data` profile as you usually would, 53for example with: 54 55```sh 56$ perf report --input perf.jit.data 57``` 58 59You should be able to annotate wasm functions and see their raw assembly. You 60should also see entries for wasm functions show up as one function and the 61name of each function matches the debug name section in the wasm file. 62 63Note that support for jitdump is still relatively new in Wasmtime, so if you 64have any problems, please don't hesitate to [file an issue]! 65 66[file an issue]: https://github.com/bytecodealliance/wasmtime/issues/new 67 68### `perf` and DWARF information 69 70If the jitdump profile doesn't give you enough information by default, you can 71also enable dwarf debug information to be generated for JIT code which should 72give the `perf` profiler more information about what's being profiled. This can 73include information like more desriptive function names, filenames, and line 74numbers. 75 76Enabling dwarf debug information for JIT code depends on how you're using 77Wasmtime: 78 79* **Rust API** - you'll want to call the [`Config::debug_info`] method. 80 81* **C API** - you'll want to call the `wasmtime_config_debug_info_set` API. 82 83* **Command Line** - you'll want to pass the `-g` flag on the command line. 84 85You shouldn't need to do anything else to get this information into `perf`. The 86perf collection data should automatically pick up all this dwarf debug 87information. 88 89### `perf` example 90 91Let's run through a quick example with `perf` to get the feel for things. First 92let's take a look at some wasm: 93 94```rust 95fn main() { 96 let n = 42; 97 println!("fib({}) = {}", n, fib(n)); 98} 99 100fn fib(n: u32) -> u32 { 101 if n <= 2 { 102 1 103 } else { 104 fib(n - 1) + fib(n - 2) 105 } 106} 107``` 108 109To collect perf information for this wasm module we'll execute: 110 111```sh 112$ rustc --target wasm32-wasi fib.rs -O 113$ perf record -k mono wasmtime --jitdump fib.wasm 114fib(42) = 267914296 115[ perf record: Woken up 1 times to write data ] 116[ perf record: Captured and wrote 0.147 MB perf.data (3435 samples) ] 117$ perf inject --jit --input perf.data --output perf.jit.data 118``` 119 120And we should have all out information now! We can execute `perf report` for 121example to see that 99% of our runtime (as expected) is spent in our `fib` 122function. Note that the symbol has been demangled to `fib::fib` which is what 123the Rust symbol is: 124 125```sh 126$ perf report --input perf.jit.data 127``` 128 129 130 131Alternatively we could also use `perf annotate` to take a look at the 132disassembly of the `fib` function, seeing what the JIT generated: 133 134```sh 135$ perf annotate --input perf.jit.data 136``` 137 138 139 140[`Config::debug_info`]: https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Config.html#method.debug_info 141