[comp.unix.i386] Benchmark Results Wanted

jpp@specialix.co.uk (John Pettitt) (06/27/89)

Terminal Benchmarks.

The  file below contains a set of public domain benchmarks written
by anvil for the Stallion card.   I am trying to gather information
on the performance of other I/O boards.  

If you have a smart I/O board in a Xenix system please take the time
to run the tests and mail me the results.  I will be posting a grand
summary to the net.  If you don't want your name or results used 
please say so.

John Pettitt
Specialix


# This is a shell archive.  Remove anything before this line
# then unpack it by saving it in a file and typing "sh file"
# (Files unpacked will be owned by you and have default permissions).
# This archive contains the following files:
#	./README
#	./popen.c
#	./tbench
#	./tbench1
#	./tbench2
#	./tbench3
#	./tinput.c
#	./total.c
#	./tsetup
#
if `test ! -s ./README`
then
echo "writing ./README"
cat > ./README << '\Rogue\Monster\'
Terminal Benchmarks.

The  file below contains a set of public domain benchmarks written
by anvil for the Stallion card.   I am trying to gather information
on the performance of other I/O boards.  

If you have a smart I/O board in a Xenix system please take the time
to run the tests and mail me the results.  I will be posting a grand
summary to the net.  If you don't want your name or results used 
please say so.

The information I would like from the results is shown below:


RESULTS OF BENCHMARKS PERFORMED USING "TBENCH" ON 16MHZ DELL-386 WITH SI-16.

		TESTS PERFORMED AT 19.2K BAUD IN "COOKED" MODE

PORTS:		1	2	3	4	5	6	7	8
%CPU:		3.2	4.4	5.7	7.0	8.3	9.3	10.9	12.3
THROUGHPUT:	18727	37594	56391	75188	93985	113208	131579	150943
AVERAGE:	18727	18797	18797	18797	18797	18868	18797	18868

PORTS:		9	10	11	12	13	14	15	16
%CPU:		13.5	15.0	16.2	17.5	18.8	20.1	21.5	22.7
THROUGHPUT:	170455	188679	207547	226415	246212	263158	281955	299625
AVERAGE:	18939	18868	18868	18868	18939	18797	18797	18727

If you can go above 16 ports then great - please do so.  If you only have 4
or 8 then thats fine too.

How to build the benchmarks.

Copy the benchmark programs to a suitable place and make the following
programs: total popen tinput

The built in make rules are all thats needed to there is no Makefile.




Running the Benchmarks.

Performing benchmarks using the XENIX/UNIX 'time' program gives a good guide to
performance but can be very inaccurate.  Any device which turns interrupts off
while running will not be timed for that period.  To achieve accurate 
benchmarks, it is necessary to get an exact measure of the ammount of CPU 
that is missing from the system due to device I/O activity. 

The 'total' program measures precisely the ammount of CPU that is missing from 
the system due to terminal I/O activity, ie. it catches time spent in device 
drivers with interrupts off.  However, before the 'total' program can be used 
it must be calibrated to the host system cpu. 

With absolutely no activity on the system run 'total -c -s60'. This will count
for 60 seconds, write a calibration file 'total.dat' and then exit.  To
select these more exact benchmarks, set the environment variable 'TEST' to 
2 in '.profile', then logout and log in again to cause the change to take 
effect. The 'tbench' program can now be run.

This benchmark generates total baud rate and average baud rate per channel 
statistics. These actual baud rates are those baud rates as percieved by the
system and not real physical baud rates, ie. they may be higher than the 
requested baud rate due to buffering on intelligent cards.

Some cards still manage to cheat the test by causing the system clock to loose 
time, some as high as 30% time lost !!. It is wise to check the time before 
and after the test by running the 'date' program.


\Rogue\Monster\
else
  echo "will not over write ./README"
fi
if `test ! -s ./popen.c`
then
echo "writing ./popen.c"
cat > ./popen.c << '\Rogue\Monster\'
/*
 * port open program
 */
#include <stdio.h>
#include <fcntl.h>
#include <termio.h>

/*
 * Main program and argument parsing
 */

#define MAXLINE 80
#define MAXFILES 100

struct termio tbuf;
int iop[MAXFILES];
int period = 10 * 60 * 60;
char buf[5120];

main(argc, argv) 
char **argv;
{
	register int i;
	int errflg, c;
	char modes[132];
	FILE *fp;

	extern char *optarg;
	extern optind;
	
	errflg = 0;
	while ((c = getopt(argc, argv, "cs:")) != EOF)
		switch(c) {
		case 'c':
			/* check++; */
			break;
		case 's':
			period = atoi(optarg);
			break;
		case '?':
			errflg++;
			break;
		}
	if (errflg || optind >= argc) {
		fprintf(stderr, "usage: popen -c -s [sleep period] [files...]\n");
		exit(2);
	}
	if ((fp = fopen("modes.dat", "r")) == (FILE *) NULL) {
		fprintf(stderr, "popen : cannot open %s\n", "modes.dat");
		exit(2);
	}
	fgets(modes, MAXLINE, fp);
	fclose(fp);
	if ((iop[0] = open(argv[optind], O_RDONLY)) < 0) {
		fprintf(stderr, "popen : cannot open %s\n", argv[optind]);
		exit(2);
	}
	modes[strlen(modes) - 1] = '\0';
	sprintf(buf, "stty %s <%s", modes, argv[optind]);
	system(buf);
	if (ioctl(iop[0], TCGETA, &tbuf) < 0) {
		fprintf(stderr, "popen : cannot set modes for %s\n", argv[optind]);
		exit(2);
	}
	for (i = 1, optind++; optind < argc; optind++, i++) {
		if ((iop[i] = open(argv[optind], O_RDONLY)) < 0) {
			fprintf(stderr, "popen : cannot open %s\n", argv[optind]);
			exit(2);
		}
		if (ioctl(iop[i], TCSETA, &tbuf) < 0) {
			fprintf(stderr, "popen : cannot set modes for %s\n", argv[optind]);
			exit(2);
		}
		
	}
	sleep(period);
}

\Rogue\Monster\
else
  echo "will not over write ./popen.c"
fi
if `test ! -s ./tbench`
then
echo "writing ./tbench"
cat > ./tbench << '\Rogue\Monster\'
#!/bin/sh

#
#                    Intelligent Terminal Subtystem
#                      Benchmark Procedures  V1.2
#
#
# Specialix and Chase support added by John Pettitt (jpp@specialix.co.uk)
#

# Define Environment Variables
#
#
: ${ARNET:=no}
: ${AFTER4:=no}
: ${BAUD:=9600}
: ${BLOCKS:=50}
: ${BRD_DIGIT:=none}
: ${DEBUG:=no}
: ${DEFAULT:=2}
: ${DIGICOM:=no}
: ${FILE:=/tmp/data.tmp}
: ${HZ:=50}
: ${LETTERS:=no}
: ${LETTERS2:=no}
: ${LINE:=0}
: ${LOOP:=0}
: ${MODE:=COOKED_OUTPUT}
: ${NBRD:=1}
: ${PORTS:=}
: ${PROMPT:=}
: ${SIGNLE:=no}
: ${T:=.d.tmp}
: ${TNAME:=/dev/tty}
: ${TEST:=2}
: ${TMODE:=COOKED}
: ${TTYPE:=OUTPUT}
: ${S_VER:=v2.0}
: ${test_done:=0}
: ${setup_done:=0}

###############################################################################
# functions								      #
###############################################################################


nkill() {
	ps | grep $1 | awk '{ printf "kill "; print $1 }' >/tmp/kill.tmp$$
	sh /tmp/kill.tmp$$
	rm -f /tmp/kill.tmp$$
}

cleanup() {
	[ $setup_done = 1 ] && nkill popen
	[ $setup_done  = 1 ] && [ $LOOP = 1 ] && nkill cat
	[ $test_done = 1 ] && [ $TTYPE = INPUT ] && nkill tinput
}

stop() {
	[ $test_done = 1 ] && [ $TEST = 2 ] && nkill total
}

clear_page() {
	echo "\033[H\033[J\c"
}


bell() {
	echo "\c"
}


#
# Page header
#
header() {
	lines=$1
	clear_page
	echo "
                     Terminal Subsystem Benchmarks $S_VER

                            Multiple Port Tests
"
	for i in $lines
	do
		echo
	done
}

getval() {
	while :
	do
		echo ${2}${3}${4}${5}${6}${7}${8}${9} >&2
		read ans
		if [ $ans ] 
		then break
		else ans=$1 ; break
		fi
	done
}

ports_build() {

if [ "$ARNET" = "yes" ]
  then PORTS="a b c d"
  else if [ "$DIGICOM" = "yes" ]
    then PORTS="11 12 13 14 15 16 17 18"
    else if [ "$LETTERS" = "yes" ] 
      then PORTS="a b c d e f g h"
      else if [ "$SINGLE" = "yes" ] 
        then PORTS="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
        else if [ "$AFTER4" = "yes" ]
          then PORTS="4 5 6 7 8 9 10 11 12 13 14 15"
          else if [ "$HEX" = "yes" ]
            then PORTS="0 1 2 3 4 5 6 7 8 9 a b c d e f"
            else if [ "$LETTERS2" = "yes" ] 
              then PORTS="a b c d e f g h i j k l m n o p"
              else if [ "$SPECIALIX" = "yes" ]
		then PORTS="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30 31 32"
		  else PORTS="00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15"
		   fi
                 fi
               fi
             fi
           fi
         fi
       fi
fi
}

###############################################################################
# main prgoram								      #
###############################################################################

#
# Trap processing Interrupt occurrs
#
	trap 'echo Terminating Benchmarks; stop; cleanup; exit $STOP' 1 2 3 15

if [ ! -w /dev/mem ]
then
	echo "Please become super user"
	exit 10 
fi

if [ ! -r /bin/time ]
then
	echo "Please install the 'time' program from the development kit"
	exit 10 
fi

header 
echo "\
              See /usr/tbench/README.bench for full details

                           Select Board to Test

                              1. Standard Comms 
                              2. Anvil Stallion / Brumby
                              3. Digicom 
                              4. Wyse-995
                              5. RT Standard Comms
                              6. Computone 4 port
                              7. Computone 8 port
                              8. Bell Technologies ICC
                              9. Arnet Smartport 4
                             10. Arnet Smartport 8
			     11. Specialix SI
			     12. Chase

                           Enter Selection ($DEFAULT) : \c"
getval $DEFAULT "\c" 
DEFAULT=$ans

case $DEFAULT in
1 ) 	NAME=com1
	BRD_DIGIT=1 
	LETTERS=yes
	: ${NTERMS:=2}
	;;

2 ) 	NAME=stallion 
	BRD_DIGIT=0 
	GETBRD=yes
	: ${NTERMS:=8}
	;;

3 ) 	NAME=digicom 
	TNAME=/dev/ttyi
	GETBRD=yes
        DIGICOM=yes
	: ${NTERMS:=8}
	;;
4 ) 	NAME=wyse-995 
	BRD_DIGIT=5 
	LETTERS=yes
	GETBRD=yes
	: ${NTERMS:=6}
	;;
5 ) 	NAME=RT_comms
	: ${NTERMS:=2}
	SINGLE=yes
	GETBRD=
	;;
6 ) 	NAME=Computone-X4P
	AFTER4=yes
	TNAME=/dev/ttya
	: ${NTERMS:=4}
	GETBRD=
	;;
7 ) 	NAME=Computone-X8P
	HEX=yes
	TNAME=/dev/ttya
	: ${NTERMS:=8}
	GETBRD=
	;;
8 ) 	NAME="Bell"
	LETTERS2=yes
	TNAME=/dev/ttyi
	: ${NTERMS:=6}
	GETBRD=
	;;
9 )		NAME="Smartport-4"
	ARNET=yes
	TNAME=/dev/tty
	: ${NTERMS:=4}
	GETBRD=
	BRD_DIGIT=1
	;;
10 )	NAME="Smartport-8"
	LETTERS=yes
	TNAME=/dev/tty
	: ${NTERMS:=8}
	GETBRD=
	BRD_DIGIT=1
	;;
11)	NAME="Specialix-SI"
	SPECIALIX=yes
	TNAME=/dev/ttya
	: ${NTERMS:=8}
	;;
12)	NAME="Chase"
	LETTERS=yes
	: ${NTERMS:=8}
	BRD_DIGIT=8
	;;	
* ) 
	echo "Not supported"
	exit 255
	;;
esac


header a a a a

[ $GETBRD ] && getval 1 "Please enter the number of boards to test (1) : \c" &&
	NBRD=$ans

getval $NTERMS "\nPlease enter the number of ports to test (" \
	$NTERMS ") : \c"
[ $NAME = com1 ]  && NBRD=$ans ; NTERMS=1
[ $NAME != com1 ] && NTERMS=$ans

getval $BAUD \
	"\nPlease enter the required baud rate (" \
	$BAUD ") : \c"
BAUD=$ans

getval $BLOCKS \
	"\nPlease enter the size in Kbytes to input/output to each port (" \
	$BLOCKS ") : \c"
BLOCKS=$ans

getval $TTYPE \
	"\nSelect required test [INPUT, OUTPUT] (" \
	$TTYPE ") : \c"
TTYPE=$ans

getval $TMODE \
	"\nPlease enter the terminal mode [COOKED, RAW] (" \
	$TMODE ") : \c"
TMODE=$ans

getval $LINE \
	"\nPlease enter the terminal line discipline number (" \
	$LINE ") : \c"
LINE=$ans

MODE=`echo ${TMODE}_${TTYPE} | tr '[a-z]' '[A-Z]'`

export BAUD BRD_DIGIT BLOCKS HEX HZ LETTERS 
export LETTERS2 LINE NTERMS NBRD PORTS PROMPT 
export TNAME MODE TTYPE TMODE SINGLE 

header a a a a a a 
setup_done=1
ports_build
./tsetup || (cleanup ; exit 255)
[ $TEST = 2 ] && header a a a a
test_done=1
./tbench${TEST}
echo "Exiting benchmark, please wait ..."
cleanup
\Rogue\Monster\
else
  echo "will not over write ./tbench"
fi
if `test ! -s ./tbench1`
then
echo "writing ./tbench1"
cat > ./tbench1 << '\Rogue\Monster\'
#! /bin/sh

#
# Terminal Benchmark #1
# 	Test Output System Loading
#
#
: ${BAUD:=exta}
: ${DEBUG:=no}
: ${FILE:=/tmp/data.tmp}
: ${MODE:=COOKED_OUTPUT}
: ${NBRD:=1}
: ${NTERMS:=8}
: ${SINGLE:=no}
: ${T:=.d.tmp}
: ${TNAME:=/dev/tty}
: ${TMODE:=COOKED}
: ${TTY:=/dev/null}
: ${TTYPE:=OUTPUT}

[ $BRD_DIGIT = none ]    && BRD_DIGIT= 

clear_page() {
	echo "\033[H\033[J\c"
}


if [ ! -w /dev/mem ]
then
	echo "Please become super user"
	exit 10 
fi

if [ ! -r /bin/time ]
then
	echo "Please install the 'time' program from the development kit"
	exit 10 
fi

rm -f /tmp/bench

clear_page

echo "\
tbench1 Version 2.0          Terminal Load Benchmark              `date '+%d/%m/%y %H:%m'`\
"
: ${total:=`expr $NTERMS \* $NBRD`} 
if [ $total = 1 ]
then
echo "\nOutput Test copying to $total terminal port (using $MODE stty flags)\n"
else
echo "\nOutput Test copying to $total terminal ports (using $MODE stty flags)\n"
fi

echo "	time ("
b=0
brd=$BRD_DIGIT
while [ $b -lt $NBRD ]
	do
	i=0
	for t in $PORTS
		do
		if [ $i -ge $NTERMS ] 
			then break
		fi
		if [ $TTYPE = INPUT ]
		then 
			echo "		tinput -b $BLOCKS ${TNAME}${brd}${t} &"
			echo "		tinput -b $BLOCKS ${TNAME}${brd}${t} &" >>/tmp/bench
		else 
			echo "		cp $FILE ${TNAME}${brd}${t} &"
			echo "		cp $FILE ${TNAME}${brd}${t} &" >>/tmp/bench
		fi
		i=`expr $i + 1`
	done
	brd=${brd:+`expr $brd + 1`}
	b=`expr $b + 1`
done

echo "  	)"
echo "wait" >>/tmp/bench

#
# Output Banner
#
cat <<!EOF >/tmp/awk.tmp
{ printf "		%-6s              %6s\n", \$1, \$2  }
!EOF

cat <<!EOF1 >/tmp/awk2.tmp
{ 
	if (\$2 ~ /:/) {
		ind = index(\$2, ":");
		min = substr(\$2, 0, ind - 1);
		sec = substr(\$2, ind + 1, 99);
		sys = min * 60 + sec;
	} else {
		sys = \$2;
	}
	if (\$4 ~ /:/) {
		ind = index(\$4, ":");
		min = substr(\$4, 0, ind - 1);
		sec = substr(\$4, ind + 1, 99);
		real = min * 60 + sec;
	} else {
		real = \$4;
	}
	printf "		Total CPU consumed    %4.1f %%\n", sys * 100.0 / real;
}
!EOF1
#

# Execute the benchmark
#

time sh /tmp/bench 2>/tmp/bench.tmp
if [ $? -ne 0 ]
then 
	echo "Benchmark error"
else 
#
# Format the output
#
	grep -v "user" </tmp/bench.tmp | grep -v "^$" >/tmp/bench2.tmp
	echo
	awk -f /tmp/awk.tmp  </tmp/bench2.tmp
	echo `grep sys /tmp/bench2.tmp` `grep real /tmp/bench2.tmp` | \
	awk -f /tmp/awk2.tmp 
fi
#
# Tidy up
#
rm -f /tmp/bench /tmp/bench.tmp /tmp/bench2.tmp /tmp/awk.tmp /tmp/awk2.tmp
rm -f $FILE
\Rogue\Monster\
else
  echo "will not over write ./tbench1"
fi
if `test ! -s ./tbench2`
then
echo "writing ./tbench2"
cat > ./tbench2 << '\Rogue\Monster\'
#! /bin/sh

#
# Terminal Benchmark #2
# 	Test Output System Loading
#
#
: ${BAUD:=9600}
: ${DEBUG:=no}
: ${FILE:=/tmp/data.tmp}
: ${MODE:=COOKED_OUTPUT}
: ${NBRD:=1}
: ${NTERMS:=8}
: ${PROMPT:=}
: ${SINGLE:=no}
: ${T:=.d.tmp}
: ${TNAME:=/dev/tty}
: ${TMODE:=COOKED}
: ${TTY:=/dev/null}
: ${TTYPE:=OUTPUT}

: ${HEADER:="$TTYPE test : "}

[ $BRD_DIGIT = none ]    && BRD_DIGIT= 
[ -r /xenix ] && : ${XENIX_SW:=-x}

clear_page() {
	echo "\033[H\033[J\c"
}

prompt() {
	echo "Press return when ready for benchmark : \c"
	read ans
	echo
}

if [ ! -w /dev/mem ]
then
	echo "Please become super user"
	exit 10 
fi

if [ ! -r /bin/time ]
then
	echo "Please install the 'time' program from the development kit"
	exit 10 
fi


bench_gen() {

b=0
brd=$BRD_DIGIT
while [ $b -lt $NBRD ]
	do
	i=0
	for t in $PORTS
		do
		if [ $i -ge $NTERMS ] 
			then break
		fi
		if [ $TTYPE = INPUT ]
		then echo "tinput -b $NBLOCKS ${TNAME}${brd}${t} &"
		else echo "cp $FILE ${TNAME}${brd}${t} &"
		fi
		i=`expr $i + 1`
	done
	brd=${brd:+`expr $brd + 1`}
	b=`expr $b + 1`
done

echo wait 
}


#
# Output Banner
#
cat <<!EOF >/tmp/awk.tmp
{ printf "          %-6s     %6s\n", \$1, \$2 }
!EOF

cat <<!EOF1 >/tmp/awk2.tmp
{ 
	if (\$2 ~ /:/) {
		ind = index(\$2, ":");
		min = substr(\$2, 0, ind - 1);
		sec = substr(\$2, ind + 1, 99);
		user = min * 60 + sec;
	} else user = \$2;
	if (\$4 ~ /:/) {
		ind = index(\$4, ":");
		min = substr(\$4, 0, ind - 1);
		sec = substr(\$4, ind + 1, 99);
		sys = min * 60 + sec;
	} else sys = \$4;
	if (\$6 ~ /:/) {
		ind = index(\$6, ":");
		min = substr(\$6, 0, ind - 1);
		sec = substr(\$6, ind + 1, 99);
		real = min * 60 + sec;
	} else real = \$6;
	printf "      CPU used         %4.1f%%", ((user + sys) * 100.0) / real;
	printf "  (excludes time in device driver with\n";
	printf "                                 interrupts off)\n";
}
!EOF1

cat <<!EOF2 >/tmp/awk3.tmp
{ 
	if (\$4 ~ /:/) {
		ind = index(\$4, ":");
		min = substr(\$4, 0, ind - 1);
		sec = substr(\$4, ind + 1, 99);
		real = min * 60 + sec;
	} else real = \$4;
	overhead = \$2;
	real = real - overhead;
	ports = \$5;
	bytes = \$10;
	printf "Benchmark overhead \n"
	printf "(accounted for)        %4.1f\n", overhead;
	printf "Aggregate baud rate %7.0f\n", (bytes * ports * 10) / real;
	printf "Average baud rate   %7.0f", (bytes * 10) / real;
	printf "   (may exceed stated baud rate on\n";
	printf "                                 intelligent cards with large buffers\n";
}
!EOF2
#

# Execute the benchmark
#

: ${total:=`expr $NTERMS \* $NBRD`}
[ $total = 1 ] && echo "$HEADER $total port \n"
[ $total != 1 ] && echo "$HEADER $total ports \n"

#
# generate script for real benchmark
#
rm -f /tmp/bench /tmp/bench.null
[ $TTYPE = INPUT ] && NBLOCKS=$BLOCKS ; export NBLOCKS
bench_gen >/tmp/bench

#
# generate script for null benchmark (to test overhead)
#
OLD_FILE=$FILE; FILE=/dev/null; export FILE
NBLOCKS=0; export NBLOCKS
bench_gen >/tmp/bench.null
FILE=$OLD_FILE; export FILE

#
# Cache all tools needed
#
time cp $FILE /dev/null 2>/dev/null

#
# do benchmark
#
time sh /tmp/bench.null 2>/tmp/overhead.tmp

[ $PROMPT ] && prompt
./total $XENIX_SW &
pid=$!
time sh /tmp/bench 2>/tmp/result1.tmp
if [ $? -ne 0 ]
then 
	echo "Benchmark error"
	kill -2 $! ; sleep 2
	kill -3 $!
else 
	kill -2 $! ; sleep 2
	kill -3 $!
#
# Format the output
#
	grep -v "^$" </tmp/result1.tmp >/tmp/result2.tmp
	awk -f /tmp/awk.tmp  </tmp/result2.tmp
	echo `grep user /tmp/result2.tmp` `grep sys /tmp/result2.tmp` \
		`grep real /tmp/result2.tmp` | awk -f /tmp/awk2.tmp 
	echo `grep real /tmp/overhead.tmp` `grep real /tmp/result2.tmp` \
		$total `ls -l $FILE` | awk -f /tmp/awk3.tmp 
	echo
fi
#
# Tidy up
#
rm -f /tmp/bench /tmp/bench.null /tmp/result?.tmp /tmp/awk?.tmp /tmp/overhead.tmp
rm -f /tmp/awk.tmp $FILE
\Rogue\Monster\
else
  echo "will not over write ./tbench2"
fi
if `test ! -s ./tbench3`
then
echo "writing ./tbench3"
cat > ./tbench3 << '\Rogue\Monster\'
#! /bin/sh

#
# Terminal Benchmark #2
# 	Test Output System Loading
#
#
: ${BAUD:=9600}
: ${DEBUG:=no}
: ${FILE:=/tmp/data.tmp}
: ${MODE:=COOKED_OUTPUT}
: ${NBRD:=1}
: ${NTERMS:=8}
: ${PROMPT:=}
: ${SINGLE:=no}
: ${T:=.d.tmp}
: ${TNAME:=/dev/tty}
: ${TMODE:=COOKED}
: ${TTY:=/dev/null}
: ${TTYPE:=OUTPUT}

: ${HEADER:="$TTYPE test : "}

[ $BRD_DIGIT = none ]    && BRD_DIGIT= 
[ -r /xenix ] && : ${XENIX_SW:=-x}

clear_page() {
	echo "\033[H\033[J\c"
}

prompt() {
	echo "Press return when ready for benchmark : \c"
	read ans
	echo
}

if [ ! -w /dev/mem ]
then
	echo "Please become super user"
	exit 10 
fi

if [ ! -r /bin/time ]
then
	echo "Please install the 'time' program from the development kit"
	exit 10 
fi


bench_gen() {

b=0
brd=$BRD_DIGIT
while [ $b -lt $NBRD ]
	do
	i=0
	for t in $PORTS
		do
		if [ $i -ge $NTERMS ] 
			then break
		fi
		if [ $TTYPE = INPUT ]
		then echo "tinput -b $NBLOCKS ${TNAME}${brd}${t} &"
		else echo "cp $FILE ${TNAME}${brd}${t} &"
		fi
		i=`expr $i + 1`
	done
	brd=${brd:+`expr $brd + 1`}
	b=`expr $b + 1`
done

echo wait 
}


#
# Output Banner
#
cat <<!EOF >/tmp/awk.tmp
{ printf "          %-6s     %6s\n", \$1, \$2 }
!EOF

cat <<!EOF1 >/tmp/awk2.tmp
{ 
	if (\$2 ~ /:/) {
		ind = index(\$2, ":");
		min = substr(\$2, 0, ind - 1);
		sec = substr(\$2, ind + 1, 99);
		user = min * 60 + sec;
	} else user = \$2;
	if (\$4 ~ /:/) {
		ind = index(\$4, ":");
		min = substr(\$4, 0, ind - 1);
		sec = substr(\$4, ind + 1, 99);
		sys = min * 60 + sec;
	} else sys = \$4;
	if (\$6 ~ /:/) {
		ind = index(\$6, ":");
		min = substr(\$6, 0, ind - 1);
		sec = substr(\$6, ind + 1, 99);
		real = min * 60 + sec;
	} else real = \$6;
}
!EOF1

cat <<!EOF2 >/tmp/awk3.tmp
{ 
	if (\$4 ~ /:/) {
		ind = index(\$4, ":");
		min = substr(\$4, 0, ind - 1);
		sec = substr(\$4, ind + 1, 99);
		real = min * 60 + sec;
	} else real = \$4;
	overhead = \$2;
	real = real - overhead;
	ports = \$5;
	bytes = \$10;
	printf "Aggregate baud rate %7.0f\n", (bytes * ports * 10) / real;
	printf "Average baud rate   %7.0f", (bytes * 10) / real;
}
!EOF2
#

# Execute the benchmark
#

: ${total:=`expr $NTERMS \* $NBRD`}
[ $total = 1 ] && echo "$HEADER $total port \n"
[ $total != 1 ] && echo "$HEADER $total ports \n"

#
# generate script for real benchmark
#
rm -f /tmp/bench /tmp/bench.null
[ $TTYPE = INPUT ] && NBLOCKS=$BLOCKS ; export NBLOCKS
bench_gen >/tmp/bench

#
# generate script for null benchmark (to test overhead)
#
OLD_FILE=$FILE; FILE=/dev/null; export FILE
NBLOCKS=0; export NBLOCKS
bench_gen >/tmp/bench.null
FILE=$OLD_FILE; export FILE

#
# Cache all tools needed
#
time cp $FILE /dev/null 2>/dev/null

#
# do benchmark
#
time sh /tmp/bench.null 2>/tmp/overhead.tmp

[ $PROMPT ] && prompt
./total $XENIX_SW &
pid=$!
time sh /tmp/bench 2>/tmp/result1.tmp
if [ $? -ne 0 ]
then 
	echo "Benchmark error"
	kill -2 $! ; sleep 2
	kill -3 $!
else 
	kill -2 $! ; sleep 2
	kill -3 $!
#
# Format the output
#
	grep -v "^$" </tmp/result1.tmp >/tmp/result2.tmp
	awk -f /tmp/awk.tmp  </tmp/result2.tmp
	echo `grep user /tmp/result2.tmp` `grep sys /tmp/result2.tmp` \
		`grep real /tmp/result2.tmp` | awk -f /tmp/awk2.tmp 
	echo `grep real /tmp/overhead.tmp` `grep real /tmp/result2.tmp` \
		$total `ls -l $FILE` | awk -f /tmp/awk3.tmp 
	echo
fi
#
# Tidy up
#
rm -f /tmp/bench /tmp/bench.null /tmp/result?.tmp /tmp/awk?.tmp /tmp/overhead.tmp
rm -f /tmp/awk.tmp $FILE
\Rogue\Monster\
else
  echo "will not over write ./tbench3"
fi
if `test ! -s ./tinput.c`
then
echo "writing ./tinput.c"
cat > ./tinput.c << '\Rogue\Monster\'

/*
 * port open program
 */
#include <stdio.h>
#include <fcntl.h>

/*
 * Main program and argument parsing
 */

#define MAXLINE 256
#define BLKSIZ 1024

char buf[MAXLINE];
char blk[BLKSIZ];
int blocks = -1;

main(argc, argv) 
char **argv;
{
	register int i;
	int errflg, c;
	FILE *fp;

	extern char *optarg;
	extern optind;
	
	errflg = 0;
	while ((c = getopt(argc, argv, "b:")) != EOF)
		switch(c) {
		case 'b':
			blocks = atoi(optarg);
			break;
		case '?':
			errflg++;
			break;
		}
	if (errflg || optind >= argc) {
		fprintf(stderr, "usage: tinput -b [blocks] files\n");
		exit(2);
	}
	if ((fp = fopen(argv[optind], "r")) < 0) {
		fprintf(stderr, "tinput : cannot open %s\n", argv[optind]);
		exit(2);
	}
	if (blocks >= 0)
		block_input(fp, blocks);
	else for (;;) {
		if (fgets(buf, MAXLINE, fp) == NULL)
			exit(2);
		if (buf[0] == 'E' && buf[1] == 'O' && buf[2] == 'F') {
			buf[strlen(buf) - 1] = '\0';
			if (strcmp(buf, "EOF!!") == 0) {
				break;
			}
		}
	}
	fclose(fp);
	exit(0);
}


block_input(fp, blocks)
FILE *fp;
{
	int got;
	long nchars;

	nchars = (long) blocks * BLKSIZ;
	while (nchars > 0) {
		if ((got = fread(buf, 1, BLKSIZ, fp)) <= 0) {
			fprintf(stderr, "tinput: fread error\n");
			exit(255);	
		}
		nchars -= got;
	}
}
\Rogue\Monster\
else
  echo "will not over write ./tinput.c"
fi
if `test ! -s ./total.c`
then
echo "writing ./total.c"
cat > ./total.c << '\Rogue\Monster\'
/*
 * total -- Real cpu availability
 */

#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#if M_XENIX
#include <sys/types.h>
#include <sys/timeb.h>
struct timeb tbuf;
#endif

/*
 * Main program and argument parsing
 */

#define FNAME "total.dat"
#define TICKS_PER_SEC	50
#define MAXDELAY	50
#define NICE_CAL	1
#define NICE_RUN	39

unsigned long lcount;
unsigned long start, finish;
unsigned long rate;
int period, calibrate, xenix, delay_inc;

extern unsigned long sys_time();
extern int intrpt();
extern int report();
extern int quit();

main(argc, argv) 
char **argv;
{
	register int i;
	int errflg, c, nvalue, old, iop;
	register FILE *fp;

	extern char *optarg;
	extern optind;
	
	errflg = 0;
	nvalue = -99;
	signal(SIGQUIT, quit);
	while ((c = getopt(argc, argv, "cxn:s:")) != EOF)
		switch(c) {
		case 'c':
			calibrate++;
			break;
		case 'n':
			nvalue = atoi(optarg);
			break;
		case 's':
			period = atoi(optarg);
			break;
		case 'x':
			xenix++;
			break;
		case '?':
			errflg++;
			break;
		}
	if (errflg) {
		fprintf(stderr, "usage: total -c -x -n [ nice value ] -s [sleep period]\n");
		exit(2);
	}
	if (access("/xenix", 0) == 0)
		xenix++;
	if (nvalue == -99)
		if (calibrate)
			nvalue = NICE_CAL;
		else nvalue = NICE_RUN;

	lcount = 0;	
	old = nice(0) + 20;
	nice(nvalue - old);

	if (calibrate) {
		if (period) {
			signal(SIGALRM, intrpt);
			alarm(period);
		} else signal(SIGINT, intrpt);

		sys_time(&start);
		loop();
	} else {
		if ((fp = fopen(FNAME, "r")) < 0) {
			fprintf(stderr, "Cannot open %s\n", FNAME);
			exit(2);
		}
		fscanf(fp, "%ld", &rate);
		if (period) {
			signal(SIGALRM, report);
			alarm(period);
		} else signal(SIGINT, report);

		sys_time(&start);
		loop();
	}
}


loop() {

	register int i;

	for (;;) {
		for (i = 0; i < MAXDELAY; i++)
			delay_inc++;
		lcount++;
	}
}


report() {
	unsigned long nticks;
	unsigned long persec;
	double cpu;

	sys_time(&finish);
	nticks = finish - start;
	if (nticks <= 0) {
		fprintf(stderr, "no time elapsed\n");
		exit(2);
	}
	persec = (lcount * TICKS_PER_SEC) / nticks;
	if (persec > rate)
		persec = rate;
	cpu = ((double) persec * 100.0) / (double) rate;
	printf("Total CPU used       %6.1f%%", 100.0 - cpu);
	printf("  (includes time in device driver with\n");
	printf("                                 interrupts off)\n");
	lcount = 0;
	if (period) {
		signal(SIGALRM, report);
		alarm(period);
	} else signal(SIGINT, report);
	sys_time(&start);
}


quit() {
	exit(0);
}


intrpt() {
	register FILE *fp;
	unsigned long nticks;

	sys_time(&finish);
	if ((fp = fopen(FNAME, "w")) < 0) {
		fprintf(stderr, "Cannot open %s\n", FNAME);
		exit(2);
	}
	nticks = finish - start;
	if (nticks <= 0) {
		fprintf(stderr, "no time elapsed\n");
		exit(2);
	}
	printf("Calibrated to %s, %ld seconds, %ld\n", FNAME,
		nticks / TICKS_PER_SEC, (lcount * TICKS_PER_SEC) / nticks);
	fprintf(fp, "%ld\n", (lcount * TICKS_PER_SEC) / nticks);
	fclose(fp);
	exit(0);
}


unsigned long
sys_time(tloc)
unsigned long *tloc;
{
#if M_XENIX
	if (xenix) {
		ftime(&tbuf);
		*tloc = tbuf.time;
		*tloc *= TICKS_PER_SEC;
		*tloc += (tbuf.millitm / (1000 / TICKS_PER_SEC));
	} else {
#endif
		time(tloc);
		*tloc *= TICKS_PER_SEC;
#if M_XENIX
	}
#endif
	return(*tloc);
}
\Rogue\Monster\
else
  echo "will not over write ./total.c"
fi
if `test ! -s ./tsetup`
then
echo "writing ./tsetup"
cat > ./tsetup << '\Rogue\Monster\'
#! /bin/sh

#
# Terminal Benchmark setup program
#	See tbench and README.bench for details
#
#
: ${AFTER4:=no}
: ${BAUD:=exta}
: ${BLOCKS:=20}
: ${DEBUG:=no}
: ${FILE:=/tmp/data.tmp}
: ${HEX:=no}
: ${LETTERS:=no}
: ${LOOP:=0}
: ${MODE:=COOKED_OUTPUT}
: ${NBRD:=1}
: ${SINGLE:=no}
: ${T:=.d.tmp}
: ${TNAME:=/dev/tty}
: ${NTERMS:=8}
: ${TMODE:=COOKED}
: ${TTY:=/dev/null}
: ${TTYPE:=OUTPUT}

need_cat=0
[ $LOOP = 1 ] && need_cat=1

[ $LETTERS = yes ] && : ${BRD_DIGIT:=1}
[ $LETTERS = no ]  && : ${BRD_DIGIT:=0}
[ $BRD_DIGIT = none ]    && BRD_DIGIT= 

if [ ! -w /dev/mem ]
then
	echo "Please become super user"
	exit 10 
fi

if [ ! -r /bin/time ]
then
	echo "Please install the 'time' program from the development kit"
	exit 10 
fi

psetup() {
	err=1
	case "$MODE" in
	COOKED_OUTPUT ) 
			echo $BAUD sane -echo ixon -ixoff -ixany line $LINE; 
			err=0 ;;
	RAW_OUTPUT    ) 
			echo $BAUD -icanon -opost -echo ixon -ixoff -ixany  line $LINE; 
			err=0 ;;
	COOKED_INPUT  ) 
			echo $BAUD sane -echo ixon ixoff -ixany line $LINE; 
			err=0 ;;
	RAW_INPUT     ) 
			echo $BAUD -icanon -opost -echo ixon ixoff -ixany  line $LINE; 
			err=0 ;;
	esac	
	[ $err = 1 ] && echo "Unknown mode $MODE" 1>&2 && exit 255
}


arg_build() {

	b=0
	brd=$BRD_DIGIT
	while [ $b -lt $NBRD ]
		do
		i=0
		args=
		for t in $PORTS
			do
			if [ $i -ge $NTERMS ] 
				then break
			fi
			args="$args ${TNAME}${brd}${t}"
			if [ $need_cat = 1 ] 
			then 
				cat >$TTY <${TNAME}${brd}${t} &
			fi
			i=`expr $i + 1`
		done
		echo opening $args 
		./popen $args & 
		b=`expr $b + 1`
		brd=${brd:+`expr $brd + 1`}
	done
}



data() {
	HOM=`pwd`
	cd /tmp
	#
	# Create test data file
	#
	cat <<!EOF3 >$T
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
cccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccc
dddddddddddddddddddddddddddddddddddddddd
dddddddddddddddddddddddddddddddddddddddd
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
ffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffff
gggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggg
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
llllllllllllllllllllllllllllllllllllllll
llllllllllllllllllllllllllllllllllllllll
mmmmmmmmmmmmmmm
!EOF3
	>$FILE
	i=0
	while [ $i -lt $BLOCKS ]
	do
		cat $T $T $T $T $T $T $T $T $T $T >>$FILE
		i=`expr $i + 10`
	done
	[ $TTYPE = INPUT ] && echo 'EOF!!\n' >>$FILE
	rm -f $T
	cd $HOM
}


echo "Setting terminal modes ..."
psetup >modes.dat

arg_build

[ $TTYPE = OUTPUT ] && echo "Create test data file ..." && data

echo "Setup done"

rm -f modes.dat
\Rogue\Monster\
else
  echo "will not over write ./tsetup"
fi
echo "Finished archive 1 of 1"
# if you want to concatenate archives, remove anything after this line
exit
-- 
John Pettitt, Specialix, Giggs Hill Rd, Thames Ditton, Surrey, U.K., KT7 0TR
{backbone}!ukc!slxsys!jpp    jpp%slxinc@uunet.uu.net     jpp@specialix.co.uk
Tel: +44-1-941-2564       Fax: +44-1-941-4098         Telex: 918110 SPECIX G
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<