package memtrace-mirage
Install
Dune Dependency
Authors
Maintainers
Sources
sha256=34b0464af8399bc8b1c9a1de907d6fcc4bab135879e1f650c63bf658cd300f8e
sha512=e9a61c4519050b7bc3f35ed9075755b1ad33cf1ac87d08293915a6b4677d8b2502f8b00d8a5b5207e6b5c92cab92c5c14c9c05b95cbbfb23b1a36f5befd43c58
README.md.html
memtrace-mirage
A streaming client for OCaml's Memprof, which generates compact traces of a program's memory use. The trace is transferred via TCP.
To profile the memory use of a unikernel, there are two options. Either the unikernel establishes a TCP connection to a listener which dumps the trace into a file, or the unikernel offers a service where upon connection of a client, the trace is dumped to.
As preparation in both cases, you need to install this package by executing opam install memtrace-mirage
and add ~packages:[ package "memtrace-mirage" ]
to your config.ml
where you call Mirage.foreign
.
From the start: establish a client connection from the unikernel
To trace the entire lifetime of the unikernel, create a client connection at startup where the trace is dumped to disk:
Run nc -l 1234 > my-unikernel.trace
to dump the trace into a file before starting the unikernel.
In the unikernel.ml
, add the following code to the start
function:
module Memtrace = Memtrace.Make(Pclock)(S.TCP)
let start () s =
(S.TCP.create_connection (S.tcp s) (Ipaddr.of_string_exn "10.0.0.1", 1234) >|= function
| Ok flow -> ignore (Memtrace.start_tracing ~context:None ~sampling_rate:1e-4 flow)
| Error e -> Logs.warn (fun m -> m "couldn't connect to tracing sink %a"
S.TCP.pp_error e)) >>= fun () ->
... rest of start ...
The unikernel provides a service for a single client
As soon as a client connects, tracing is started. The tracing is only stopped when the client disconnects. Only a single client is permitted.
First start the unikernel, then execute nc 10.0.0.2 1234 > my-unikernel.trace
. Quit the nc
process once you like to stop tracing.
In the unikernel.ml
, add the following code:
module Memtrace = Memtrace.Make(Pclock)(S.TCP)
let start () s =
S.TCP.listen (S.tcp s) ~port:1234
(fun f ->
(* only allow a single tracing client *)
match Memtrace.Memprof_tracer.active_tracer () with
| Some _ ->
Logs.warn (fun m -> m "tracing already active");
S.TCP.close f
| None ->
Logs.info (fun m -> m "starting tracing");
let tracer = Memtrace.start_tracing ~context:None ~sampling_rate:1e-4 f in
Lwt.async (fun () ->
S.TCP.read f >|= fun _ ->
Logs.warn (fun m -> m "tracing read returned, closing");
Memtrace.stop_tracing tracer);
Lwt.return_unit);
... rest of start ...
Trace file analysis
The resulting trace files can be analysed with some simple command-line tools from the memtrace
opam package, but the recommended interface is the memtrace viewer, which lives at:
https://github.com/janestreet/memtrace_viewer
This repository code is based on memtrace.