## MLton 20241230

# MLtonProfile

    signature MLTON_PROFILE =
       sig
          structure Data:
             sig
                type t

                val equals: t * t -> bool
                val free: t -> unit
                val malloc: unit -> t
                val write: t * string -> unit
             end

          val isOn: bool
          val withData: Data.t * (unit -> 'a) -> 'a
       end

`MLton.Profile` provides Profiling control from within the program, allowing you to profile individual portions of your program. With `MLton.Profile`, you can create many units of profiling data (essentially, mappings from functions to counts) during a run of a program, switch between them while the program is running, and output multiple `mlmon.out` files.

- `isOn`

  a compile-time constant that is false only when compiling `-profile no`.

- `type Data.t`

  the type of a unit of profiling data. In order to most efficiently execute non-profiled programs, when compiling `-profile no` (the default), `Data.t` is equivalent to `unit ref`.

- `Data.equals (x, y)`

  returns true if the `x` and `y` are the same unit of profiling data.

- `Data.free x`

  frees the memory associated with the unit of profiling data `x`. It is an error to free the current unit of profiling data or to free a previously freed unit of profiling data. When compiling `-profile no`, `Data.free x` is a no-op.

- `Data.malloc ()`

  returns a new unit of profiling data. Each unit of profiling data is allocated from the process address space (but is not in the MLton heap) and consumes memory proportional to the number of source functions. When compiling `-profile no`, `Data.malloc ()` is equivalent to allocating a new `unit ref`.

- `write (x, f)`

  writes the accumulated ticks in the unit of profiling data `x` to file `f`. It is an error to write a previously freed unit of profiling data. When compiling `-profile no`, `write (x, f)` is a no-op. A profiled program will always write the current unit of profiling data at program exit to a file named `mlmon.out`.

- `withData (d, f)`

  runs `f` with `d` as the unit of profiling data, and returns the result of `f` after restoring the current unit of profiling data. When compiling `-profile no`, `withData (d, f)` is equivalent to `f ()`.

## Example

Here is an example, taken from the `examples/profiling` directory, showing how to profile the executions of the `fib` and `tak` functions separately. Suppose that `fib-tak.sml` contains the following.

    structure Profile = MLton.Profile

    val fibData = Profile.Data.malloc ()
    val takData = Profile.Data.malloc ()

    fun wrap (f, d) x =
       Profile.withData (d, fn () => f x)

    val rec fib =
       fn 0 => 0
        | 1 => 1
        | n => fib (n - 1) + fib (n - 2)
    val fib = wrap (fib, fibData)

    fun tak (x,y,z) =
       if not (y < x)
          then z
       else tak (tak (x - 1, y, z),
                 tak (y - 1, z, x),
                 tak (z - 1, x, y))
    val tak = wrap (tak, takData)

    val rec f =
       fn 0 => ()
        | n => (fib 38; f (n-1))
    val _ = f 2

    val rec g =
       fn 0 => ()
        | n => (tak (18,12,6); g (n-1))
    val _ = g 500

    fun done (data, file) =
       (Profile.Data.write (data, file)
        ; Profile.Data.free data)

    val _ = done (fibData, "mlmon.fib.out")
    val _ = done (takData, "mlmon.tak.out")

Compile and run the program.

    % mlton -profile time fib-tak.sml
    % ./fib-tak

Separately display the profiling data for `fib`

    % mlprof fib-tak mlmon.fib.out
    5.77 seconds of CPU time (0.00 seconds GC)
    function   cur
    --------- -----
    fib       96.9%
    <unknown>  3.1%

and for `tak`

    % mlprof fib-tak mlmon.tak.out
    0.68 seconds of CPU time (0.00 seconds GC)
    function  cur
    -------- ------
    tak      100.0%

Combine the data for `fib` and `tak` by calling `mlprof` with multiple `mlmon.out` files.

    % mlprof fib-tak mlmon.fib.out mlmon.tak.out mlmon.out
    6.45 seconds of CPU time (0.00 seconds GC)
    function   cur
    --------- -----
    fib       86.7%
    tak       10.5%
    <unknown>  2.8%