$Header: /net/hr1/robot/MissionLab-devel/CVS/repository/src/hardware_drivers/hserver/ipm/README,v 1.1.1.1 2006/07/12 13:37:56 endo Exp $

"Copyright (c) 1995 The Regents of the University of California.  
All rights reserved."

Permission to use, copy, modify, and distribute this software and
its documentation for any purpose, without fee, and without
written agreement is hereby granted, provided that the above
copyright notice and the following two paragraphs appear in all
copies of this software.

IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY
PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE
SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE
UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."

Introduction
------------

The Interval Performance Monitoring (IPM) package provides a portable
interface for taking performance related statistics over an "interval"
of a code's execution.  The interval is delimited by explicit calls to
IPM start and stop routines.  The package also provides a simple,
portable interface to read high resolution timers.

In this release, the only statistic that can be measured is time.
Future releases will give access to other performance information.
Tables below list the timing information supported in this release for
various platforms.  This document corresponds to IPM version 2.0.

Philosophy
----------

The IPM package is intended to hide details of any performance
monitoring hardware from the application source code.  The calls
simply annotate where measurement should take place.  It is
anticipated that usually an external agent, either the user or a
performance measurement tool, will run the application several times
to extract relevant performance information.  Environment variables
are used to communicate from the external agent to the IPM library
which measurements should take place, and the IPM library uses ASCII
strings to communicate back performance information.

IPM timer
---------

SYNOPSIS

#include "IPM_timer.h"

double IPM_timer_resolution(void);
double IPM_timer_range(void);
void   IPM_timer_clear(IPM_timer*);
void   IPM_timer_start(IPM_timer*);
void   IPM_timer_stop(IPM_timer*);
double IPM_timer_read(const IPM_timer*);
char * IPM_timer_format(void);
void   IPM_timer_report(const char* tag, const IPM_timer*, char *buf);
double IPM_timer_get_time(void);

cc -I/u/spert/include -o main main.c <other-libs> -L/u/spert/<arch>/lib -lipm

This version of IPM initializes automatically on the first call to one
of the above IPM routines.  The initialization parses environment
variables to determine which timing module to use in all timers.  It
may also perform various system calls to access and configure hardware
timers and counters.

The IPM_timer struct holds data for a single timer instance.  The
IPM_timer struct should not be modified by the user program except via
IPM_timer_* calls.

Two calls can be used to determine the properties of the current timer
module: IPM_timer_resolution() returns the time quantum of the clock
in seconds.  IPM_timer_range() returns the largest interval, measured
in seconds, that can be timed without overflowing the timer.

IPM_timer_clear() clears the timer instance, resetting accumulated
time to zero.

IPM_timer_start() starts the interval timer, and IPM_timer_stop()
stops the interval timer. The IPM_timer_stop() call accumulates time
in the timer instance, so multiple executions of the same interval of
code will have their execution time summed by default.

IPM_timer_read() returns the accumulated time in seconds for the given
timer instance.

IPM_timer_format() returns a printf-style format string with
resolution and width sufficient to hold the significant digits of
readings from the current timer module.  The format string is of the
form "%<w>.<p>f", where <w> is the total field width and <p> is the
number of fractional digits.  The string is allocated from an internal
buffer and should not be modified.

IPM_timer_report() prepares an ASCII string containing the timer
value.  The first argument, if non-NULL, is an arbitrary string tag
that is used to label this timer report for the external agent.  The
user is responsible for ensuring sufficient space in the buffer passed
to the IPM_timer_report() call.  The macro IPM_TIMER_REPORT_LEN gives
the number of characters required to hold the formatted report minus
the length of the user-supplied tag.  The user is responsible for
passing these ASCII strings back to the environment over the
appropriate channel.

The IPM_timer_get_time() call simply reads the clock and returns a
value in seconds.

Example Code
------------

The following is a sample session using the IPM package on a SunOS 4.x
system.

%cat time_foo.c
#include <stdio.h>

/* Get timer declarations. */
#include "IPM_timer.h"

extern void foo();              /* Function to be timed. */

int
main()
{
    IPM_timer t;                /* Place for timer info. */
    char report[IPM_TIMER_REPORT_LEN+3]; /* Place to put timer report. */

    IPM_timer_clear(&t);        /* Initialize interval statistics. */

    IPM_timer_start(&t);        /* Start measurement. */
    foo();                      /* Routine to be measured. */
    IPM_timer_stop(&t);         /* Stop measurement. */

    IPM_timer_report("foo", &t, report); /* Format report string. */

    puts(report);               /* Output report string. */

    return 0;
}
%cc -I/u/spert/include -o time_foo time_foo.c -L/u/spert/sun4/lib -lipm
%./time_foo
IPM_timer: tag=foo module=gettimeofday type=real time=         0.188858
%env IPM_timer_module=getrusage ./time_foo
IPM_timer: tag=foo module=getrusage type=process time=         0.12
%env IPM_timer_module=getrusage IPM_timer_type=system ./time_foo
IPM_timer: tag=testing module=getrusage type=system time=         0.00
%

A system may provide several alternative timers.  A collection of
related timers is called a timing module.  In the SunOS4 example
above, there are two timing modules.  The default is a real time
module using the gettimeofday(2) call.  This reads a high precision
real timer.

On BSD-compatible systems, the getrusage(2) call can be used to take
process related timings.  The getrusage timing module is selected by
using the "env IPM_timer_module=getrusage" command to set the
environment variable before invoking the program.  The resolution of
the getrusage module is only around 10 ms under SunOS4.  The
getrusage module provides 3 different timer types: process, user, and
system, corresponding to total process time, user time and system time
respectively.  The environment variable "IPM_timer_type" selects
between the timer types and can be set to "process", "user", or
"system".

Supported Timing Modules
------------------------

The following lists the various timing modules currently available,
and the systems on which they are supported.

gettimeofday
------------

This timing module measures real time using the gettimeofday(2) call.

Supported on:

        SunOS4          (1e-6s resolution)
        SunOS5          (1e-6s resolution)
        HP-UX           (roughly 1e-6s resolution)
        SGI Irix 4.0.5  (1e-2s resolution)
        SGI Irix 5.3    (1e-6s resolution)
        SGI Irix 6.1    (1e-6s resolution)
        AIX             (1e-2s resolution)
        Linux-1.2.8     (1e-4s resolution?)
        DEC OSF v3.2    (1e-6s resolution?)

getrusage
---------

Measures cpu time spent running a process using the BSD getrusage(2) call.

The getrusage module has three timer types:

        "process"  total cpu time used by this process.
        "user"     cpu time spent in user mode by this process.
        "system"   cpu time spent in system mode on behalf of this process.

process time is the sum of user and system times.

Supported on:

        Sun-3 & SunOS4  (2e-2s resolution)
        Sun-4 & SunOS4  (1e-2s resolution)
        SGI Irix 4.0.5  (1e-2s resolution)
        SGI Irix 5.3    (1e-6s resolution)
        SGI Irix 6.1    (1e-6s resolution)
        AIX             (1e-2s resolution)
        Linux-1.2.8     (1e-2s resolution?)
        DEC OSF v3.2    (1e-6s resolution?)

gethrtimer
----------

This module measures real time using the high resolution gethrtime(2)
timer on SunOS5 systems.  Also, measures process time using the
not-so-high resolution gethrvtime(2) call.

The gethrtimer module has two timer types:

        "real"    wall clock time.
        "process" cpu time used by this process.


Supported on:

        SunOS5 (5e-7s resolution "real", 1e-2 resolution "process")

syssgi
------

Measures real time using the counter register located on the bus of
most SGI systems.

Should work on all SGI systems.  Tested on:

        SGI Indigo R4K (IP20),    Irix 5.3 (4e-8s resolution).
        SGI Challenge R8K (IP26), Irix 6.1 (2e-8s resolution).

gettimer
--------

This module measures real time using the gettimer(?) calls provided by
AIX.

Supported on:

        AIX (resolution 2.56e-07s)

t0vcount
--------

This module measures real time using the high resolution counter
register (vcount) accessible via the vector unit on a T0 processor.

The resolution depends on the speed of the T0 clock, which is under
software control in the SPERT-II system.  Typically this will be 40
MHz (resolution 25e-9s) on a SPERT-II board.

Timing information is meaningless on the T0 ISA interpreter, but cycle
accurate on the T0 RTL simulator.

Supported on:

        SPERT-II running spert0 (resolution 25e-9s)

IPM_timer_test
--------------

This program tests out the IPM package by making calls to all routines
in the library and printing out the results.

IPM_timer_stats
---------------

This program measures the timer overhead and resolution of the IPM
timer.

    IPM_timer_stats [-help] [-n <#outer>] [-i #inner]
        -help       Show this message.
        -n <#outer> Use this many outer loop timer readings.  Default is 100.
        -i <#inner> Call routine this many times in inner loop.  By default,
                    the program automatically determines this parameter.

The program uses the IPM timer to measure its own overhead and
resolution.  Two sets of tests are run.

The first just uses the timer to measure the time inside an
IPM_timer_start/IPM_timer_stop pair of calls with no intervening code.
If the timer has sufficient resolution, this will give a reasonably
accurate measure of the call overhead.  The routine takes <#outer>
readings and reports statistics including various percentiles,
including the minimum, median, and maximum, as well as the mean and
standard deviation.

The second test can be used to estimate the timer overhead in cases
where the timer does not have high enough resolution to measure its
own call overhead.  This test places an inner timing loop around the
IPM_timer_start/IPM_timer_stop calls and measures the time for
<#inner> iterations using a separate timer in an outer loop.  The -i
argument sets the number of timer calls to make within the inner loop
for each timing sample.  If the -i argument is not given, the program
automatically finds a value that gives an acceptable resolution (~1%)
for the call overhead timing, and runs for at least 0.01s.  The timing
loop is run <#outer> times and then statistics are reported including
various percentiles, including the minimum, median, and maximum, as
well as the mean and standard deviation.  The times returned by this
test are that of one complete IPM_timer_start/IPM_timer_stop call.
This time will be approximately twice the overhead added to each
interval measured inside the pair.

In both tests, an estimate of the timing resolution is obtained by
looking for the smallest measured difference between any two timing
calls.

Contact
-------

Send all comments/corrections/suggestions to:

        krste@icsi.berkeley.edu

An IPM home page has been set up at URL:

        http://www.icsi.berkeley.edu/~krste/IPM.html

The distribution may be ftp-ed from:

        ftp://ftp.icsi.berkeley.edu/pub/realsys/ipm-2.0.tar.gz

Authors/Acknowledgements/Thanks
-------------------------------

Krste Asanovic <krste@icsi.berkeley.edu>

    Wrote most of it.

David Johnson <davidj@icsi.berkeley.edu> 

    Worked on some of the configure stuff, and wrote first version of
    the t0vcount module.

David Cortesi <cortesi@barchester.wpd.sgi.com>

    Helped out with understanding the SGI timers, and supplied example
    code to read SGI timers portably.
