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![perf report output](assets/perf-report-fib.png)
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![perf annotate output](assets/perf-annotate-fib.png)
139
140[`Config::debug_info`]: https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Config.html#method.debug_info
141