#lang scribble/manual
@;{ manual.scrbl -- Scribble documentation for ppamltracer-racket
Copyright (C) 2013, 2014 Galois, Inc.
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see .
To contact Galois, complete the Web form at
or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
Oregon, 97204-1622. }
@(require (for-label racket/base
racket/sequence))
@(require (for-label ppamltracer))
@title{ppamltracer}
ppamltracer is a lightweight, portable tracing library designed for explicit instrumention of generated code.
If you're writing a compiler and need hard data on your optimizer's efficacy, ppamltracer is the library for you.
This Racket library provides a high-level API on top of the libppamltracer C API.
ppamltracer's usage can be summed up in a couple lines:
@racketblock[
(require ppamltracer)
(let/tracer [tracer "/tmp/my_report"]
(let/phase tracer [phase "phase 1"]
(with-phase-running phase
(do-stuff)))
(let/phase tracer [phase "phase 2"]
(with-phase-running phase
(do-other-stuff))
(with-phase-running phase
(do-yet-more-stuff))))
]
This creates a report with the total runtime of @racket[do-stuff] recorded as "phase 1" and the total runtime of @racket[do-other-stuff] and @racket[do-yet-more-stuff] combined as "phase 2".
@secref{getting-started} contains a more lengthy example.
ppamltracer writes trace logs in the @hyperlink["http://tu-dresden.de/zih/otf/"]{Open Trace Format}, a free and open standard developed by the Zentrum für Informationsdienste und Hochleistungsrechnen (Center for Information Services and High-Performance Computing) at the Technical University of Dresden.
We developed ppamltracer as part of DARPA's @hyperlink["http://darpa.mil/Our_Work/I2O/Programs/Probabilistic_Programming_for_Advanced_Machine_Learning_(PPAML).aspx"]{Probabilistic Programming for Advancing Machine Learning} (PPAML) project.
@section[#:tag "getting-started"]{Getting Started}
This basic example demonstrates using ppamltracer to trace two functions -- a factorial function and a Fibonacci number generator.
@#reader scribble/comment-reader (racketblock
;; simple.rkt -- basic ppamltracer example
;; This file is in the public domain.
(require racket/sequence)
(require ppamltracer)
(define (fact phase n)
;; Record that we're running inside the factorial phase.
(with-phase-running phase
;; Compute the factorial.
(if (= n 0)
1
(* n (fact phase (- n 1))))))
(define (fib phase n)
;; Record that we're running inside the Fibonacci phase.
(with-phase-running phase
;; Compute the nth Fibonacci number.
(case n
[(0 1) n]
[else (+ (fib phase (- n 1)) (fib phase (- n 2)))])))
;; Start ppamltracer.
(let/tracer [tracer "/tmp/simple_report"]
;; Register the factorial phase.
(let/phase tracer [phase "fact"]
;; Print factorials.
(printf "Factorials: ")
(sequence-for-each (lambda (n) (printf "~a " (fact phase n)))
(in-range 40))
(printf "\n"))
;; Register the Fibonacci phase.
(let/phase tracer [phase "fib"]
;; Print Fibonacci numbers.
(printf "Fibonacci numbers: ")
(sequence-for-each (lambda (n) (printf "~a " (fib phase n)))
(in-range 16))
(printf "\n")))
)
@section{API in Depth}
@defmodule[ppamltracer]
@subsection{Tracers}
ppamltracer is fundamentally a set of stateful operations; the @racket[tracer] data type holds the state ppamltracer needs to operate properly.
@defproc[(tracer? [obj any/c])
boolean?]{
Evaluates to @racket[#t] if and only if @racket[obj] is a @racket[tracer].
}
@defproc[(call-with-tracer [report-name-base path-string?]
[proc (-> tracer? A)])
A]{
Creates a new @racket[tracer].
The @racket[tracer] will save trace reports in Open Trace Format; all trace file paths will begin with @racket[report-name-base].
}
@defform[#:id let/tracer
#:literals (tracer)
(let/tracer [tracer report-name-base] body ...)
#:contracts ([report-name-base path-string?])]{
Macro version of @racket[call-with-tracer].
Equivalent to
@racketblock[
(call-with-tracer report-name-base (lambda (tracer) body ...))
]
}
@subsection{Phases}
A @racket[phase] represents a phase of execution about which the user wishes to gather timing statistics.
@defproc[(phase? [obj any/c])
boolean?]{
Evaluates to @racket[#t] if and only if @racket[obj] is a @racket[phase].
}
@defproc[(call-with-phase [tracer tracer?]
[phase-name string?]
[proc (-> phase? A)])
A]{
Creates a new @racket[phase] attached to @racket[tracer] and named @racket[phase-name].
}
@defform[#:id let/phase
#:literals (phase)
(let/phase tracer [phase name] body ...)
#:contracts ([tracer tracer?]
[name string?])]{
Macro version of @racket[call-with-phase].
Equivalent to
@racketblock[
(call-with-phase tracer name (lambda (phase) body ...))
]
}
@subsection{Tracing}
@defproc[(call-with-phase-running [phase phase?]
[proc (-> A)])
A]{
Runs @racket[proc], associating information about its timing and execution with @racket[phase] in the trace report.
Should @racket[proc] throw an exception, @racket[call-with-phase-running] will stop tracing before propagating the exception up the stack.
}
@defform[#:id with-phase-running
#:literals (phase)
(with-phase-running phase body ...)
#:contracts ([phase phase?])]{
Macro version of @racket[call-with-phase-running].
Equivalent to
@racketblock[
(call-with-phase-running phase (lambda () body ...))
]
}