$Header: /u/spert/src/IPM/RCS/README,v 1.25 1996/08/08 01:18:55 krste 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 -L/u/spert//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 "%.

f", where is the total field width and

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 /* 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 Wrote most of it. David Johnson Worked on some of the configure stuff, and wrote first version of the t0vcount module. David Cortesi Helped out with understanding the SGI timers, and supplied example code to read SGI timers portably.