dennis@nosc.mil (Dennis Cottel) (02/20/91)
In the February 1991 issue of Unix Review, there is an article by Bentley, Kernighan, and Van Wyk describing how to measure the cost of various capabilities of your system hardware and software. Would someone who has already typed in the source be willing to email it to me or post it? Dennis Cottel, dennis@NOSC.MIL, (619) 553-1645 Naval Ocean Systems Center, San Diego, CA 92152
jvs@osf.org (Jim Van Sciver) (02/20/91)
There have been enough requests for the Unix Review timing routine that I thought it would be worth posting it. Be forewarned that I have made some small changes to the written text. I did just enough to do some OSF/1 timings on a DECstattion. Enjoy! Jim Van Sciver Phone: (617) 621-7206 Open Software Foundation FAX: (617) 225-2782 11 Cambridge Center Email: jvs@osf.org Cambridge MA 02142 uunet!osf.org!jvs ------------------------------- Cut Here ------------------------------- /* time.c -- produce a 1-page summary of cpu times of various C constructs * to port to a new machine, change the following: * BASEN: Start around 10000, increase by *10 until no quesstion marks * Macro processor: define ANSIMAC 1 for Ansii C, undef for old C * Times: probably change CLICKPERSEC, may change jobclicks() * WARNRANGE: print ? after CPU time if max clicks - min clicks > * WARNRANGE * mean clicks */ #include <stdio.h> #include <math.h> #undef ANSIIMAC #define ANSIIMAC 1 #define BASEN 1000000 #define WARNRANGE 0.4 struct stacknode { int val; struct stacknode *next; }; typedef struct stacknode *Stackp; Stackp stackroot; void push(i) int i; { Stackp p; p = (Stackp) malloc(sizeof(struct stacknode)); p->val = i; p->next = stackroot; stackroot = p; } int pop() { int i; i = stackroot->val; stackroot = stackroot->next; return i; } /* Objects associated with CPU times -- may have to change * CLICKSPERSEC is defined as HZ on many systems * Typical values of CLICKSPERSEC: Vax=60 Cray=105296000 * For large values, also change %5d in macro loop1, 99999 in minclicks; */ #ifdef mips #define CLICKSPERSEC 256 #endif /* mips */ #include <sys/types.h> #include <sys/times.h> int jobclicks() { struct tms buffer; times(&buffer); return (int) (buffer.tms_utime + buffer.tms_stime); } /* Main macros for experiments */ #ifdef ANSIIMAC #define quoted(TEXT) #TEXT #else #define quoted(TEXT) "TEXT" #endif #define loop1(CODE) loop1ctr++; \ for (i = 0; i < n; i++) { CODE; } \ loop1next = jobclicks(); \ thisclicks = loop1next - loop1start; \ sumclicks += thisclicks; \ if (thisclicks < minclicks) minclicks = thisclicks; \ if (thisclicks > maxclicks) maxclicks = thisclicks; \ printf("%5d", loop1next - loop1start); \ loop1start = loop1next; #define loop(CODE) printf(" %-30s", quoted(CODE)); \ minclicks = 999999; maxclicks = -1; sumclicks = 0; \ loop1ctr = 0; \ loop1start = jobclicks(); \ loop1(CODE) \ loop1(CODE) \ i0 = i1 + i2 + i3; \ loop1(CODE) \ i0 = i1 + i2 + i3 - i1 -i2 -i3; \ loop1(CODE) \ i0 = i1 + i2 + i3 + i1*i2 + i2*i3 + i1*i3; \ loop1(CODE) \ queststr = ""; \ if (loop1ctr * (maxclicks - minclicks) > WARNRANGE * sumclicks) \ queststr = "?"; \ lastmics = sumclicks * 1000000.0 / (CLICKSPERSEC * n * loop1ctr); \ printf("%10.2f%s\n", lastmics - basemics, queststr); #define title(TEXT) printf("%s (n=%d)\n", TEXT, n); /* The experiment */ int sum1(a) int a; {return a; }; int sum2(a, b) int a, b; {return a + b; }; int sum3(a, b, c) int a, b, c; {return a + b + c; }; main() { int loop1start, loop1next, loop1ctr; float lastmics, basemics; int minclicks, maxclicks, sumclicks, thisclicks; int i, n, basen; int i0, i1, i2, i3, i4; float f0, f1, f2, f3; int *v; char *queststr; char s[100]; char fname[20]; FILE *fp; /* The following strings are variables because some macro processors don't handle quoted strings in quoted arguments */ char *s0123456789 = "0123456789"; char *sa123456789 = "a123456789"; char *s12345 = "12345"; char *s123_45 = "123.45"; char *sd = "%d"; char *sdn = "%d\n"; char *sf = "%f"; char *sf62 = "%f6.2"; setbuf(stdout, (char *) 0); /* No buffering to watch output */ printf(" Operation Clicks for each trial "); printf(" Mics/N\n"); basen = BASEN; n = basen; title("Null Loop") i0 = i1 = i2 = i3 = 5; f0 = f1 = f2 = f3 = 5.0; basemics = 0.0; loop({}) basemics = lastmics; title("Int Operations"); i1 = i2 = i3 = 5; loop(i1++) loop(i1 = i2) loop(i1 = i2 + i3) loop(i1 = i2 - i3) loop(i1 = i2 / i3) loop(i1 = i2 % i3) title("Float Operations"); f1 = f2 = f3 = 5.0; loop(f1 = f2) loop(f1 = f2 + f3) loop(f1 = f2 - f3) loop(f1 = f2 * f3) loop(f1 = f2 / f3) title("Numeric Conversions"); f1 = 123456.789; i1 = 123456; loop(i1 = f1) loop(f1 = i1) title("Integer Vector Operations"); v = (int *)malloc(n * sizeof(int)); for (i = 0; i < n; i++) v[i] = 0; loop(v[i] = i) loop(v[v[i]] = i) loop(v[v[v[i]]] = i) free(v); title("Control Structures"); i1 = i2 = i3 = 5; loop(if (i == 5) i1++) loop(if (i != 5) i1++) loop(while (i < 0) i1++) loop(i1 = sum1(i2)) loop(i1 = sum2(i2,i3)) loop(i1 = sum3(i2,i3,i4)) n = basen/100; strcpy(fname, "junk"); title("Input/Output"); strcpy(s, "1234\n"); fp = fopen(fname, "w"); loop(fputs(s,fp)) close(fp); fp = fopen(fname, "r"); loop(fgets(s, 9, fp)) close(fp); fp = fopen(fname, "w"); loop(fprintf(fp, sdn, i)) close(fp); fp = fopen(fname, "r"); loop(fscanf(fp, sd, &i1)) close(fp); n = basen/100; title("Malloc"); loop(free(malloc(8))) loop(push(i)) loop(i1 = pop()) n = basen/10; title("String Functions"); loop(strcpy(s, s0123456789)) loop(i1 = strcmp(s, s)) loop(i1 = strcmp(s, sa123456789)) n = basen/100; title("String/Number Conversions"); loop(i1 = atoi(s12345)) loop(sscanf(s12345, sd, &i1)) loop(sprintf(s, sd, i)) loop(f1 = atof(s123_45)) loop(sscanf(s123_45, sf, &f1)) loop(sprintf(s, sf62, 123.45)) n = basen/100; title("Math Functions"); loop(i1 = rand()) f2 = 5.0; loop(f1 = log(f2)) loop(f1 = exp(f2)) loop(f1 = sin(f2)) loop(f1 = sqrt(f2)) }