[comp.benchmarks] Unix Review

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))
}