home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume9
/
tbench
/
cpu.c
next >
Wrap
C/C++ Source or Header
|
1989-11-12
|
7KB
|
381 lines
/* :ex:se ts=4 sw=4 This program formatted with tabs 4 */
/****************************************************
* This software released to the public domain *
* without restrictions of any kind. *
****************************************************/
/*
* NAME
* cpu - CPU activity sensor
*
* SYNOPSIS
* cpu [ -cdr ] [-s delay ] [ -t time ]
*
* DESCRIPTION
* CPU is a program to detect the overall processor
* activity present in a system as part of performance
* testing. CPU must be calibrated on an idle
* system, where it times a test loop and writes
* the results to the file /tmp/.cpu. Thereafter
* CPU may be run at any time when the system is
* under load. Using CPU statistics provided by
* the system, and by measuring the test loop slowdown,
* the program can approximate general system CPU loading.
*
* -c Calibrate. Should be run when the system
* is as idle as possible; single user mode
* is best.
*
* -d Turn on debugging flags.
*
* -r Test repeatedly until interrupted.
*
* -s delay Sleep for the given delay time before
* beginning the test.
*
* -t time Run the test for time seconds.
*
* On completion, CPU outputs the following 3 time values.
*
* process The amount of time the system reported
* that other processes were running.
*
* interrupt The slowdown of the test loop not reflected
* by the system statistics. Most likely this
* time was consumed by interrupt routines, by
* task switching overhead, or because activity
* was synchronized to the system clock.
*
* total The total slowdown of the test loop relative
* to the speed measured at calibration time.
*
* The total time is the most interesting, since it reflects
* the real processor utilization abosorbed by other processes.
* Proper use of the other two numbers is left as a problem
* for the reader.
*
* WARNINGS
* CPU is astoundingly inaccurate in systems with different
* speed memories. In some systems (eg i386 with 16 bit
* memory on the AT bus) it is not uncommon for calibration
* runs to vary by a factor of 2 or more. There is no
* solution but to change the memory or find another machine.
*
* The order of parameters 2 & 3 on setvbuf() vary from
* system, and are even inconsistent between the manuals
* and the libraries on stock system V.2. You are wise
* to check the order of the parameters on your system and
* set the SETVBUF #define accordingly.
*/
#if !defined(lint)
char whatstring[] = "@(#)cpu.c 3.1 9/22/89" ;
#endif
#if sun
#define BSD 1
#endif
#if BSD
# include <sys/types.h>
# include <sys/time.h>
# include <sys/resource.h>
#else
# include <sys/types.h>
# include <sys/times.h>
# include <sys/param.h>
#endif
#include <signal.h>
#include <ctype.h>
#include <stdio.h>
#define uchar unsigned char
#define ushort unsigned short
#define ulong unsigned long
extern char *optarg ;
extern int optind ;
extern char *ttyname() ;
extern long atol() ;
extern void (*signal())() ;
extern unsigned sleep() ;
#if BSD
#else
extern unsigned alarm() ;
extern void exit() ;
extern void perror() ;
extern time_t times() ;
#endif
#if BSD
# define TICS 1000 /* Fractional seconds */
# define MS(tv) (1000000L / TICS * (tv).tv_sec + (tv).tv_usec / TICS)
#else
# define TICS HZ
#endif
#define CALFILE "/tmp/.cpu"
double speed ; /* Speed of the processor running */
double process ; /* Amount of the machine allocated to us */
int debug ; /* Debug flag */
int delay ; /* Delay before start */
int timeout ; /* Alarm occurred flag */
int interrupt ; /* Got an interrupt */
ulong rep ; /* Repeat count */
/*******
* Catch interrupts.
*/
sigalrm()
{
timeout = 1 ;
}
sigint()
{
interrupt = 1 ;
}
/*******
* delay - Routine to chew time.
*/
hog()
{
static int a = 1 ;
static int b = 2 ;
static int c = 3 ;
a += b ;
b += c ;
c += a ;
}
/*******
* measure - Procedure to measure our access to the CPU.
*/
measure(runtime)
int runtime ; /* Time period */
{
ulong real ;
ulong sys ;
ulong user ;
ulong count ;
#if BSD
struct timeval tv ;
struct rusage ru ;
#else
struct tms tms ;
#endif
/*
* Get real time and system time.
*/
#if BSD
(void) gettimeofday(&tv, (struct timezone *)0) ;
real = MS(tv) ;
(void) getrusage(RUSAGE_SELF, &ru) ;
user = MS(ru.ru_utime) ;
sys = MS(ru.ru_stime) ;
#else
real = times(&tms) ;
user = tms.tms_utime ;
sys = tms.tms_stime ;
#endif
if (debug) (void) fprintf(stderr,"Cpu started\n") ;
timeout = 0 ;
count = 0 ;
(void) signal(SIGALRM, sigalrm) ;
(void) alarm((unsigned) runtime) ;
(void) nice(40) ;
while (!timeout && !interrupt)
{
hog() ;
count++ ;
}
(void) nice(-40) ;
#if BSD
(void) gettimeofday(&tv, (struct timezone *)0) ;
real = MS(tv) - real ;
(void) getrusage(RUSAGE_SELF, &ru) ;
user = MS(ru.ru_utime) - user ;
sys = MS(ru.ru_stime) - sys ;
#else
real = times(&tms) - real ;
user = tms.tms_utime - user ;
sys = tms.tms_stime - sys ;
#endif
process = (double) user / (double) real ;
speed = user ? (double) count / (double) user : 0.0 ;
if (debug)
{
(void) fprintf(stderr,
"real=%ld, sys=%ld, user=%ld, count=%ld\n",
real, sys, user, count) ;
(void) fprintf(stderr, "raw process=%.5f, speed=%.5f\n",
process, speed) ;
}
}
main(argc, argv)
int argc ;
char **argv ;
{
double cprocess ;
double cspeed ;
int calibrate ;
int runtime = 30 ;
int err ;
int c ;
FILE *cfile ;
char iobuf[1024] ;
char buf[200] ;
#if SETVBUF
(void) setvbuf(stderr, _IOLBF, iobuf, sizeof(iobuf)) ;
#else
(void) setvbuf(stderr, iobuf, _IOLBF, sizeof(iobuf)) ;
#endif
(void) nice(-40) ;
calibrate = 0 ;
err = 0 ;
while ((c = getopt(argc, argv, "cdrs:t:")) != -1)
{
switch (c)
{
case 'c':
calibrate++ ;
break ;
case 'd':
debug++ ;
break ;
case 'r':
rep = -1 ;
break ;
case 's':
delay = atoi(optarg) ;
break ;
case 't':
runtime = atoi(optarg) ;
break ;
case '?':
err++ ;
}
}
if (err || optind < argc)
{
(void) fprintf(stderr,
"usage: %s [ -cd ] [ -t time ]\n", argv[0]) ;
exit(2) ;
}
if (delay) (void) sleep((unsigned) delay) ;
if (calibrate)
{
measure(runtime) ;
if ((cfile = fopen(CALFILE, "w")) == 0)
{
perror(CALFILE) ;
exit(1) ;
}
(void) fprintf(cfile, "%f %f\n", process, speed) ;
(void) fprintf(stderr,
"Calibrated process=%f, speed=%f\n", process, speed) ;
}
else
{
if ((cfile = fopen(CALFILE, "r")) == 0)
{
perror(CALFILE) ;
(void) fprintf(stderr,
"Perhaps you should run \"%s -c\" first.\n", argv[0]) ;
exit(1) ;
}
if ( fscanf(cfile, "%lf %lf", &cprocess, &cspeed) != 2
|| cprocess == 0
|| cspeed == 0
)
{
(void) fprintf(stderr,
"%s file does not contain calibrated speed.\n", CALFILE) ;
}
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
(void) signal(SIGINT, sigint) ;
for (;;)
{
measure(runtime) ;
#if 0
process /= cprocess ;
#endif
speed /= cspeed ;
if (debug)
{
(void) fprintf(stderr, "normalized process=%.5f, speed=%.5f\n",
process, speed) ;
}
(void) sprintf(buf,
"TIME process=%.1f, interrupt=%.1f, total=%.1f\n",
100 * (1 - process) * speed,
100 * (1 - speed),
100 * (1 - process * speed)) ;
(void) write(2, buf, (unsigned) strlen(buf)) ;
if (rep == 0 || interrupt) break ;
rep-- ;
}
}
return(0) ;
}