|
3 | 3 | [Work in Progress] |
4 | 4 |
|
5 | 5 | The microchassis is all about increasing the observability of Rust binaries. |
| 6 | + |
| 7 | +## Memory Profiling with jemalloc |
| 8 | + |
| 9 | +Example intergration with `hyper` endpoint: |
| 10 | + |
| 11 | +```rust |
| 12 | +use microchassis::profiling::jeprof; |
| 13 | +``` |
| 14 | + |
| 15 | +```rust |
| 16 | + let symbol_table = Arc::new(jeprof::SymbolTable::load()?); |
| 17 | + let make_service = hyper::service::make_service_fn(move |_conn| { |
| 18 | + let symbol_table = Arc::clone(&symbol_table); |
| 19 | + let service = hyper::service::service_fn(move |req| handle(Arc::clone(&symbol_table), req)); |
| 20 | + async move { Ok::<_, io::Error>(service) } |
| 21 | + }); |
| 22 | + let addr = SocketAddr::from(([127, 0, 0, 1], 12345)); |
| 23 | + tokio::spawn(async move { hyper::Server::bind(&addr).serve(make_service).await }); |
| 24 | +``` |
| 25 | + |
| 26 | +```rust |
| 27 | +async fn handle( |
| 28 | + symbol_table: Arc<jeprof::SymbolTable>, |
| 29 | + req: hyper::Request<hyper::Body>, |
| 30 | +) -> io::Result<hyper::Response<hyper::Body>> { |
| 31 | + let (parts, body) = req.into_parts(); |
| 32 | + let body = hyper::body::to_bytes(body).await?; |
| 33 | + let req = hyper::Request::from_parts(parts, body.into()); |
| 34 | + |
| 35 | + let resp = jeprof::router(symbol_table.as_ref(), req)?; |
| 36 | + |
| 37 | + let (parts, body) = resp.into_parts(); |
| 38 | + let body = hyper::Body::from(body); |
| 39 | + let resp = hyper::Response::from_parts(parts, body); |
| 40 | + |
| 41 | + Ok(resp) |
| 42 | +} |
| 43 | +``` |
| 44 | + |
| 45 | +Keep symbol in release binary. |
| 46 | + |
| 47 | +```toml |
| 48 | +[profile.release] |
| 49 | +debug = 1 |
| 50 | +strip = false |
| 51 | +``` |
| 52 | + |
| 53 | +Disable ASLR if necessary or install the `disable_aslr` helper tool. |
| 54 | + |
| 55 | +```shell |
| 56 | +cargo install microchassis |
| 57 | +``` |
| 58 | + |
| 59 | +Use package manager to install `jeprof` or download from |
| 60 | +<https://github.com/jemalloc/jemalloc/blob/master/bin/jeprof.in>, rename to |
| 61 | +`jeprof` and edit its version (x.y.z-0-commit) inside. |
| 62 | + |
| 63 | +(optional) Install `graphviz` package. |
| 64 | + |
| 65 | +(optional) Install `flamegraph.pl` from |
| 66 | +<https://raw.githubusercontent.com/brendangregg/FlameGraph/master/flamegraph.pl>. |
| 67 | + |
| 68 | +Run your binary with profiling enabled and activated: |
| 69 | + |
| 70 | +```shell |
| 71 | +MALLOC_CONF=prof:true,prof_active:true,lg_prof_sample:8 disable_aslr ./myserver |
| 72 | +``` |
| 73 | + |
| 74 | +(Use `_RJEM_MALLOC_CONF` if jemalloc is built with prefix.) |
| 75 | + |
| 76 | +Or start with profiling not active and activate later via HTTP endpoint: |
| 77 | + |
| 78 | +```shell |
| 79 | +MALLOC_CONF=prof:true,prof_active:false,lg_prof_sample:8 disable_aslr ./myserver |
| 80 | +``` |
| 81 | + |
| 82 | +```shell |
| 83 | +curl -X POST 'http://myserver:12345/pprof/conf?prof.active:true' |
| 84 | +``` |
| 85 | + |
| 86 | +Fetch a profile dump with `jeprof` and generate a flame/icicle graph. |
| 87 | + |
| 88 | +```shell |
| 89 | +jeprof --raw 'http://myserver:12345/pprof/heap' >heap.prof |
| 90 | +jeprof --collapsed heap.prof | flamegraph.pl --reverse --invert >heap.svg |
| 91 | +``` |
0 commit comments