package memtrace-mirage

  1. Overview
  2. Docs
Streaming client for Memprof using MirageOS API

Install

Dune Dependency

Authors

Maintainers

Sources

memtrace-mirage-0.2.1.2.2.tbz
sha256=34b0464af8399bc8b1c9a1de907d6fcc4bab135879e1f650c63bf658cd300f8e
sha512=e9a61c4519050b7bc3f35ed9075755b1ad33cf1ac87d08293915a6b4677d8b2502f8b00d8a5b5207e6b5c92cab92c5c14c9c05b95cbbfb23b1a36f5befd43c58

Description

Generates compact traces of a program's memory use.

Published: 22 May 2022

README

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.

Dependencies (6)

  1. lwt >= "5.5.0"
  2. ptime >= "1.0.0"
  3. mirage-clock >= "4.0.0"
  4. mirage-flow >= "3.0.0"
  5. ocaml >= "4.11.0" & < "5.0"
  6. dune >= "2.3"

Dev Dependencies

None

Conflicts

None