home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-02-01 | 57.6 KB | 1,806 lines |
- Newsgroups: comp.sources.unix
- From: ben@bytepb.byte.com (Ben Smith @ BYTE)
- Subject: v25i110: BYTE Benchmarks, V3.1, Part03/04
- Sender: sources-moderator@pa.dec.com
- Approved: vixie@pa.dec.com
-
- Submitted-By: ben@bytepb.byte.com (Ben Smith @ BYTE)
- Posting-Number: Volume 25, Issue 110
- Archive-Name: byte-benchmarks3.1/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 4)."
- # Contents: Run doc/bench.doc src/big.c src/dhry_1.c
- # Wrapped by vixie@cognition.pa.dec.com on Sun Feb 2 16:27:40 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Run' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Run'\"
- else
- echo shar: Extracting \"'Run'\" \(13305 characters\)
- sed "s/^X//" >'Run' <<'END_OF_FILE'
- X#! /bin/sh
- X#################### set your defaults here ##############
- XFLAVOR="" # flavor of UNIX: if not determined by script: SysV or BSD
- XFULL_SUITE="dhry2 dhry2reg arithoh register short int long float double syscall pipe context1 spawn execl fstime C shell dc hanoi"
- X###############################################################################
- X# The BYTE UNIX Benchmarks - Release 3
- X# Module: Run SID: 3.11 5/15/91 19:30:14
- X#
- X###############################################################################
- X# Bug reports, patches, comments, suggestions should be sent to:
- X#
- X# Ben Smith, Tom Yager at BYTE Magazine
- X# ben@bytepb.byte.com tyager@bytepb.byte.com
- X# BIX: bensmith tyager
- X#
- X###############################################################################
- X# Modification Log:
- X# $Header: run,v 5.2 88/01/12 06:23:43 kenj Exp $
- X# Ken McDonell, Computer Science, Monash University
- X# August 1, 1983
- X# 3/89 - Ben Smith - BYTE: globalized many variables, modernized syntax
- X# 5/89 - commented and modernized. Removed workload items till they
- X# have been modernized. Added database server test.
- X# 11/14/89 - Made modifications to reflect new version of fstime
- X# and elimination of mem tests.
- X# 10/22/90 - Many tests have been flipped so that they run for
- X# a specified length of time and loops are counted.
- X# 4/3/91 - Cleaned up and debugged several test parameters - Ben
- X# 4/9/91 - Added structure for creating index and determing flavor of UNIX
- X# 4/26/91 - Made changes and corrections suggested by Tin Le of Sony
- X# 5/15/91 - Removed db from distribution
- X#
- X###############################################################################
- ID="@(#)Run:3.11 -- 5/15/91 19:30:14";
- version="3.11"
- X#######################################################################
- X# General Purpose Benchmark
- X# based on the work by Ken McDonell, Computer Science, Monash University
- X#
- X# You will need ...
- X# awk cat cc chmod comm cp date dc df echo ed expr
- X# kill ls make mkdir rm sed test time touch tty umask who
- X# AND /bin/time
- X# to generate result indexes, you will also need ...
- X# join
- X#
- X#
- umask 022 # at least mortals can read root's files this way
- X#
- if [ -z "$FLAVOR" ]
- then
- X # determine flavor of UNIX from number of lines generated by /bin/tim
- X Fcount=`/bin/time date 2>&1 | wc -l | sed 's/ //g'`
- X case "$Fcount"
- X in
- X 2) FLAVOR="BSD";;
- X 5) FLAVOR="SysV";;
- X *) echo "Flavor of UNIX is not known."
- X echo "Please define FLAVOR in Run script"
- X exit;;
- X esac
- fi
- X#if SysV use 'uname -a' -- if BSD use 'hostname'
- if [ $FLAVOR = "SysV" ]
- then UNAME="uname -a"
- else UNAME="hostname"
- fi
- export FLAVOR
- X# check that the required files are in the proper places
- if make check
- X then :
- X else make all
- fi
- X#
- X#
- X# establish full paths to directories
- PWD=`pwd`
- HOMEDIR=${HOMEDIR-.}
- cd $HOMEDIR
- HOMEDIR=`pwd`
- cd $PWD
- X
- BINDIR=${BINDIR-${HOMEDIR}/pgms}
- cd $BINDIR
- BINDIR=`pwd`
- cd $PWD
- X# let's extend the path to this directory
- PATH="${PATH}:${BINDIR}"
- X
- SCRPDIR=${SCRPDIR-${HOMEDIR}/pgms}
- cd $SCRPDIR
- SCRPDIR=`pwd`
- cd $PWD
- X
- TMPDIR=${HOMEDIR}/tmp
- cd $TMPDIR
- TMPDIR=`pwd`
- cd $PWD
- X
- RESULTDIR=${RESULTDIR-${HOMEDIR}/results}
- cd $RESULTDIR
- RESULTDIR=`pwd`
- cd $PWD
- X
- TIMEACCUM=${TIMEACCUM-${RESULTDIR}/times}
- X
- TESTDIR=${TESTDIR-${HOMEDIR}/testdir}
- cd $TESTDIR
- TESTDIR=`pwd`
- cd $PWD
- X
- export BINDIR TMPDIR RESULTDIR PATH TESTDIR TIMEACCUM
- X#
- cat ${BINDIR}/byte.logo # display banner
- rm -f ${TIMEACCUM} # clean out old time accumulation file
- echo "kill -9 $$" > ${TMPDIR}/kill_run ; chmod u+x ${TMPDIR}/kill_run
- X#
- arithmetic="arithoh register short int long float double"
- system="syscall pipe context1 spawn execl fstime"
- misc="C dc hanoi"
- dhry="dhry2 dhry2reg" # dhrystone loops
- load="shell" # cummulative load tests
- index="double dhry2 execl fstime context1 shell"
- X#
- args="" # the accumulator for the bench units to be run
- runoption="N"
- X# generate list of bench programs
- for word
- do # do level 1
- X case $word
- X in
- X all)
- X ;;
- X arithmetic)
- X args="$args $arithmetic"
- X ;;
- X dhry)
- X args="$args $dhry"
- X ;;
- X load)
- X args="$args $load"
- X ;;
- X misc)
- X args="$args $misc"
- X ;;
- X speed)
- X args="$args $arithmetic $system"
- X ;;
- X system)
- X args="$args $system"
- X ;;
- X index)
- X args="$args $index"
- X ;;
- X -q|-Q)
- X runoption="Q" #quiet
- X shift
- X ;;
- X -v|-V)
- X runoption="V" #verbose
- X shift
- X ;;
- X -d|-D)
- X runoption="D" #debug
- X shift
- X ;;
- X *)
- X args="$args $word"
- X ;;
- X esac
- X
- done # end do level 1
- X#if no benchmark units have be specified, do them all
- X# the - option of set implies no options; any list following
- X# becomes the line arguments (replacing any that may exist)
- set - $args
- if test $# -eq 0 #no arguments specified
- X then
- X set - $FULL_SUITE
- fi
- X
- if test "$runoption" = 'D'
- then
- X set -x
- X set -v
- fi
- X
- date=`date`
- TMPTIMES=${TMPDIR}/$$.tmp
- LOGFILE=${RESULTDIR}/log
- REPORTLOG=${RESULTDIR}/report
- X#add old log to accumulated log or move it
- if test -w ${RESULTDIR}/log
- then
- X if test -w ${RESULTDIR}/log.accum
- X then
- X cat ${RESULTDIR}/log >> ${RESULTDIR}/log.accum
- X rm ${RESULTDIR}/log
- X else
- X mv ${RESULTDIR}/log ${RESULTDIR}/log.accum
- X fi
- fi
- echo "| BYTE UNIX Benchmarks (Version $version)" >>$LOGFILE
- echo "| System --" `$UNAME` >>$LOGFILE
- echo "| Start Benchmark Run: `date`" >>$LOGFILE
- echo "| " `who | wc -l` "interactive users." >>$LOGFILE
- X#if not specified, do each bench 6 iterations
- iter=${iterations-6}
- if test $iter -eq 6
- then
- X longloop="1 2 3 4 5 6"
- X shortloop="1 2 3"
- else # generate list of loop numbers
- X short=`expr \( $iter + 1 \) / 2`
- X longloop=""
- X shortloop=""
- X while test $iter -gt 0
- X do # do level 1
- X longloop="$iter $longloop"
- X if test $iter -le $short
- X then
- X shortloop="$iter $shortloop"
- X fi
- X iter=`expr $iter - 1`
- X done # end do level 1
- fi #loop list genration
- X####################################################################
- X############## the major control loop ##############################
- X####################################################################
- for bench # line argument processing
- do # do level 1
- X # set some default values
- X prog=${BINDIR}/$bench # the bench name is default program
- X paramlist="#" # a dummy parameter to make anything run
- X testdir="${TESTDIR}" # the directory in which to run the test
- X prepcmd="" # preparation command or script
- X parammsg=""
- X repeat="$longloop"
- X stdout="$LOGFILE"
- X stdin=""
- X options=""
- X logmsg=""
- X cleanopt="-l $TMPTIMES"
- X bgnumber=""
- X trap "${SCRPDIR}/cleanup.sh -L $LOGFILE -a; exit" 1 2 3 15
- X echo "" >>$LOGFILE
- X ###################### select the bench specific values ##########
- X case $bench
- X in
- X dhry2)
- X options=${dhrytime-10}
- X logmsg="Dhrystone 2 without register variables"
- X ;;
- X
- X dhry2reg)
- X options=${dhrytime-10}
- X logmsg="Dhrystone 2 using register variables"
- X ;;
- X
- X arithoh|register|short|int|long)
- X options=${arithtime-10}
- X logmsg="Arithmetic Test (type = $bench)"
- X ;;
- X
- X float|double)
- X options=${arithtime-10}
- X logmsg="Arithmetic Test (type = $bench)"
- X ;;
- X
- X syscall)
- X options=${systime-10}
- X logmsg="System Call Overhead Test"
- X ;;
- X
- X context1)
- X options=${systime-10}
- X logmsg="Pipe-based Context Switching Test"
- X ;;
- X
- X pipe)
- X options=${systime-10}
- X logmsg="Pipe Throughput Test"
- X ;;
- X
- X spawn)
- X options=${systime-10}
- X logmsg="Process Creation Test"
- X ;;
- X
- X execl)
- X options=${systime-10}
- X logmsg="Execl Throughput Test"
- X ;;
- X
- X fstime)
- X logmsg='Filesystem Throughput Test ($param second test)'
- X where=${where-${TMPDIR}}
- X cleanopt="-f $TMPTIMES"
- X options='$param '"$where"
- X paramlist=${seconds-"10 30"}
- X parammsg='Test Time: $param secs'
- X ;;
- X
- X C)
- X logmsg="C Compiler Test"
- X prog="looper ${looper-60} cc cctest.c"
- X stdout=/dev/null
- X repeat="$shortloop"
- X cleanopt="-m $TMPTIMES"
- X rm -f ${TESTDIR}/cctest.o ${TESTDIR}/a.out
- X ;;
- X
- X shell)
- X logmsg='Shell scripts ($param concurrent)'
- X prog="looper ${looper-60} multi.sh"
- X repeat="$shortloop"
- X stdout=/dev/null
- X paramlist=${background-"1 2 4 8 "}
- X parammsg='$param concurrent background processes'
- X bgnumber='$param'
- X cleanopt="-m $TMPTIMES"
- X ;;
- X
- X dc)
- X logmsg="Dc: sqrt(2) to 99 decimal places"
- X prog="looper ${looper-60} dc"
- X stdin=dc.dat
- X stdout=/dev/null
- X cleanopt="-m $TMPTIMES"
- X ;;
- X
- X hanoi)
- X options=${systime-10}
- X stdout=/dev/null
- X logmsg="Recursion Test--Tower of Hanoi"
- X parammsg='$param Disk Problem:'
- X ;;
- X
- X *) ${BINDIR}/cleanup.sh -L $LOGFILE -r "run: unknown benchmark \"$bench\" \n Known benchmarks are: \n $FULL_SUITE" -a
- X exit 1
- X ;;
- esac
- X################################################################
- X###################### the main task ###########################
- X###################### run the bench ###########################
- X################################################################
- X# each of those variables are now used in a general way
- X#
- X for param in $paramlist
- X do # level 2
- X param=`echo $param | sed 's/_/ /g'` # be sure that spaces are used
- X eval Lmsg='"'$logmsg'"'
- X eval opt='"'$options'"' # evaluate any vars in options
- X eval prep='"'$prepcmd'"' # evaluate any prep command
- X eval bg='"'$bgnumber'"' # evaluate bgnumber string
- X rm -f $TMPTIMES # remove any tmp files
- X
- X # if the test requires mulitple concurrent processes,
- X # prepare the background process string (bgstr)
- X # this is just a string of "+"s that will provides a
- X # parameter count for a "for" loop
- X bgstr=""
- X if test "$bg" != ""
- X then
- X count=`expr "$bg"`
- X while test $count -gt 0
- X do
- X bgstr="+ $bgstr"
- X count=`expr $count - 1`
- X done
- X fi
- X #
- X echo "TEST|$Lmsg" >>$TMPTIMES
- X echo "FLAVOR|${FLAVOR}" >>$TMPTIMES
- X if [ "$runoption" != 'Q' ]
- X then
- X echo ""
- X if [ $FLAVOR = "SysV" ]
- X then echo "$Lmsg \c"
- X else echo -n "$Lmsg "
- X fi
- X
- X fi
- X for i in $repeat # loop for the specified number
- X do # do depth 3
- X if [ "$runoption" != 'D' ] # level 1
- X then
- X # regular Run - set logfile to go on signal
- X trap "${BINDIR}/cleanup.sh -L $LOGFILE -i $i $cleanopt -a; exit" 1 2 3 15
- X else
- X trap "exit" 1 2 3 15
- X fi #end level 1
- X # make an attempt to flush buffers
- X sync; sync; sleep 10
- X # display heartbeat
- X if [ "$runoption" != 'Q' ]
- X then
- X if [ $FLAVOR = "SysV" ]
- X then echo " $i\c" # display repeat number
- X else echo -n " $i"
- X fi
- X fi
- X pwd=`pwd` # remember where we are
- X cd $testdir # move to the test directory
- X if [ "$runoption" = "V" ]
- X then
- X echo
- X echo "BENCH COMMAND TO BE EXECUTED:"
- X echo "$prog $opt"
- X fi
- X
- X # execute any prepratory command string
- X if [ -n "$prep" ]
- X then
- X $prep 2>&1 >>$stdout
- X fi
- X ############ THE BENCH IS TIMED ##############
- X if test "$stdin" = ""
- X then # without redirected stdin
- X /bin/time $prog $opt $bgstr 2>>$TMPTIMES >>$stdout
- X else # with redirected stdin
- X /bin/time $prog $opt $bgstr <$stdin 2>>$TMPTIMES >>$stdout
- X fi
- X /bin/time $benchcmd
- X ###############################################
- X cd $pwd # move back home
- X status=$? # save the result code
- X if test $status != 0 # must have been an error
- X then
- X if test -f $TMPTIMES # is there an error file ?
- X then
- X cp $TMPTIMES ${TMPDIR}/save.$bench.$param
- X ${SCRPDIR}/cleanup.sh -L $LOGFILE -i $i $cleanopt -r \
- X "run: bench=$bench param=$param fatalstatus=$status" -a
- X else
- X ${SCRPDIR}/cleanup.sh -L $LOGFILE -r \
- X "run: bench=$bench param=$param fatalstatus=$status" -a
- X fi
- X exit # leave the script if there are errors
- X fi # end level 1
- X done # end do depth 3 - repeat of bench
- X if [ "$runoption" != 'D' ]
- X then
- X ${SCRPDIR}/cleanup.sh -L $LOGFILE $cleanopt # finalize this bench
- X # with these options
- X # & calculate results
- X fi
- X done # end do depth 2 - end of all options for this bench
- X
- X ########### some specific cleanup routines ##############
- X case $bench
- X in
- X C)
- X rm -f ${TESTDIR}/cctest.o ${TESTDIR}/a.out
- X ;;
- X
- X fstime)
- X sync; sleep 20
- X ;;
- X esac
- X if [ "$runoption" != 'Q' ]
- X then
- X echo ""
- X fi
- done # end do level 1 - all benchmarks requested
- X########## a few last items for the end ##############
- echo "" >>$LOGFILE
- echo "End Benchmark Run: `date`" >>$LOGFILE
- echo " " `who | wc -l` "interactive users." >>$LOGFILE
- X# create the report
- X${SCRPDIR}/report.sh $LOGFILE > $REPORTLOG
- X${SCRPDIR}/index.sh ${SCRPDIR}/index.base $LOGFILE >> $REPORTLOG
- if [ "$runoption" != 'Q' ]
- then
- X echo ""
- X echo "=============================================================="
- X cat $REPORTLOG
- fi
- X
- exit
- X########################### Amen ######################
- END_OF_FILE
- if test 13305 -ne `wc -c <'Run'`; then
- echo shar: \"'Run'\" unpacked with wrong size!
- fi
- chmod +x 'Run'
- # end of 'Run'
- fi
- if test -f 'doc/bench.doc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'doc/bench.doc'\"
- else
- echo shar: Extracting \"'doc/bench.doc'\" \(14682 characters\)
- sed "s/^X//" >'doc/bench.doc' <<'END_OF_FILE'
- X@BT
- X
- X[TITLE]BYTE's UNIX Benchmarks
- X[DEK]Separating fact from fiction in the exploding UNIX empire
- X[TOC]Before you jump into the UNIX pool, see how your favorite system stacks
- up against the rest of the pack.
- X
- Ben Smith
- X
- In making purchase decisions, it's difficult to know whom to believe. Each
- vendor claims, predictably, that their products are better than the
- competition's, but how does one prove, or debunk, these claims?
- X Cost and performance typically top the list of considerations for those
- seeking to purchase equipment, and while cost can be easily compared,
- performance cannot, and comparing costs without analyzing each system's
- relative value is a worthless exercise.
- X When DOS became popular, it allowed for the development of performance
- measurement programs, benchmarks, that would run on any system that ran DOS.
- BYTE's lab technicians set about creating their own, and the BYTE DOS
- benchmarks were born. Dozens of systems have been clocked using these
- facilities, and each review of a new DOS-based system includes the results of
- these benchmarks.
- X This is all very well, but while DOS is installed on a great many systems,
- it is no longer the !ITAL!only!ENDITAL! popular multi-platform operating
- system. User demands for greater expandability, better performance and
- multi-tasking have turned UNIX systems into one of the fastest growing
- segments of the market. When UNIX stepped from minicomputers to workstations,
- it established itself as the defacto OS for an exciting new breed of machine.
- Now, with solid implementations for affordable Intel and Motorola-based
- platforms, UNIX is making a name for itself in the PC realm. As UNIX finds
- its way into the mainstream, it is necessary to have the tools to objectively
- measure not only the performance of various hardware platforms, but of
- different versions of UNIX as well.
- X
- X!SUBHED!Unix is Not MS-DOS!ENDSUBHED!
- Conceptually, BYTE's UNIX benchmarks are the same as BYTE's MS-DOS
- benchmarks: We have combined evaluation of both low-level operations and
- high-level applications type programs to highlight the performance of the
- entire system.
- X But UNIX is considerably different from MS-DOS. In the first place, it is a
- X!ITAL!multi!ENDITAL!-tasking, !ITAL!multi!ENDITAL!-user operating system. It
- is also portable, able to run on many different kinds of computers. MS-DOS is
- a !ITAL!single!ENDITAL!-tasking, !ITAL!single!ENDITAL!-user operating system,
- and it is intended to run on essentially one kind of computer, an IBM-PC or
- PC ``clone,'' utilizing a specific class of processor from Intel. As a
- result, the UNIX benchmarks differ from their MS-DOS counterparts. Even
- though there are some equivalent low-level tests, you will find that even
- these run differently; the popular Dhrystone benchmark commonly gives
- different results, on the same hardware, when run under both DOS and UNIX.
- The reason? Different compilers are being used, and the underlying operating
- systems and services are wildly different.
- X Another important difference is that Microsoft is the only real source of
- DOS; other suppliers simply repackage Microsoft's basic operating system
- under other names. In contrast, there are many different kinds of UNIX, and
- while similarities exist (the core UNIX from Dell, Everex and Interactive
- Systems are virtually the same), there are UNIX and UNIX-like operating
- systems that differ greatly from one another. Conclusion: The UNIX benchmarks
- are evaluating the implementation of UNIX and the resident compiler as well
- as the hardware on which it is running (the MS-DOS and Apple Macintosh
- benchmarks use a common compiler, the public-domain Small C).
- X With so many variables, what is constant? Well, we have established a
- baseline, SCO Xenix 386 version 2.3.1. running on the Everex 386/33 with 4
- Mbytes of RAM and an 80387 math coprocessor. While it isn't UNIX per se
- X(because AT&T decides which implementations may be called ``UNIX''), it is
- more popular than any other PC UNIX implementation. It is specifically
- designed for 80386-based computers with full 32 bit memory access. The Everex
- X386/33 was chosen because it is one of today's highest performance 386
- computers properly configured to run the full 32 bit operating system. (Some
- X386 computers cannot access memory through single 32 bit operations; small
- matter if you are just running MS-DOS, an 8 bit operating system, but serious
- if you want to run UNIX.) This combination of system and OS is timely, but
- we'll continue to adjust the baseline as needed to reflect the installed PC
- and workstation UNIX base.
- X
- X!SUBHED!The Low Level Bench Programs!ENDSUBHED!
- The BYTE UNIX benchmarks consist of eight groups of programs: arithmetic,
- system calls, memory operations, disk operations, dhrystone, database
- operations, system loading, and miscellaneous. These can be roughly divided
- into the low-level tests (arithmetic, system calls, memory, disk, and
- dhrystone) and high-level tests (database operations, system loading, and the
- C-compiler test that is part of the miscellaneous set).
- X The Dhrystone test is known more formally as ``Dhrystone 2''. It performs
- no floating-point operations, but it does involve arrays, character strings,
- indirect addressing, and most of the non-floating point instructions that
- might be found in an application program. It also includes conditional
- operations and other common program flow controls. The output of the test is
- the number of dhrystone loops per second. It is used in the BYTE benchmarks
- because of its wide selection of operations and because it is one of the most
- widely run benchmark programs.
- X A future version of the BYTE UNIX benchmarks will include the Whetstone
- benchmark test program, as well. The Whetstone benchmark is conceptually
- similar to the Dhrystone, but with an emphasis on math; it is a mix of
- floating point and integer arithmetic, function calls, array operations,
- conditionals, and transcendental function calls.
- X All the arithmetic tests have the same source code with different data
- types substituted for the operations: register, short, int, long, float,
- double, and an empty loop for calculating the overhead required by the
- program. The actual test involves assignment, addition, subtraction,
- multiplication, and division. Very simple. But don't bother running the float
- and double precision test unless you have a math co-processor; what takes a
- math co-processor system 15 seconds, may take an unaided processor 30 minutes
- or more!
- X The system call tests are: system call overhead, pipe throughput, pipe
- context switching, spawning of child processes, execl (replacement of the
- current process by a new process), and file read, write, and copy. The system
- call overhead test evaluates the time required to do iterations of
- X!MONO!dup()!ENDMONO!, !MONO!close()!ENDMONO!, !MONO!getpid()!ENDMONO!,
- X!MONO!getuid()!ENDMONO!, and !MONO!umask()!ENDMONO! calls.
- X The pipe throughput test has no real counterpart in real-world programming;
- in it, a single process opens a pipe (an inter-process communications channel
- that works rather like its plumbing namesake) to itself and spins a megabyte
- around this short loop. You might call this the pipe overhead test. The
- context switching pipe test is more like a real-world application; the test
- program spawns a child process with which it carries on a bi-directional pipe
- conversation.
- X The spawn test creates a child process which immediately dies after its own
- X!MONO!fork()!ENDMONO!. The process is repeated over and over. Similarly, the
- exec test is a process that repeatedly changes to a new incarnation. One of
- the arguments passed to the new incarnation is the number of remaining
- iterations (there has to be some control, after all).
- X The file read, write, and copy tests capture the number of characters that
- can be written, read, and copied in a specified time (default is 10 seconds).
- If you run this test with the minimum element (1 second), you should see a
- significantly higher value for all operations if your system implements disk
- cacheing. Be sure you have plenty of disk space before you run this test.
- X
- X!SUBHED!The High-Level Bench Programs!ENDSUBHED!
- To qualify as a high-level test, the test must involve operations that a
- real-world application program might employ, including heavy use of the CPU
- and disk. At the time of writing this article, we have currently implemented
- only the system loading and database tests, but we will be adding several new
- tests in the months ahead.
- X The system loading test is a shell script that is run by 1, 2, 4, and 8
- concurrent processes. The script consists of an alphabetic sort one file to
- another; taking the octal dump of the result and doing a numeric sort to a
- third file; running grep on the result of the alphabetic sort file;
- X!MONO!tee!ENDMONO!ing the result to a file and to !MONO!wc!ENDMONO! (word
- count); writing the final result to a file; and removing all of the resulting
- files. This script was used in the original BYTE UNIX benchmarks (1983), but
- the source file is several magnitudes larger than the original.
- X The C compile and link is nothing more than that.
- X The database operations consist of random read, write, and add operations
- on a database file. The operations are handled by a server process; the
- requests come from client processes. The test is run with 1, 2, 4, and 8
- client processes. The test employs semaphores and message queues. Semaphores
- are being used less and less these days. BSD systems use sockets instead in
- place of both of these System V.3 IPC utilities. System V.4 offers both. This
- test is being rewritten using sockets, but since Xenix doesn't implement
- sockets, our baseline configuration becomes instantly obsolete when we
- replace the database test. Just another one of those little problems in
- trying to create journalistic computer benchmarks: any program that has been
- fully debugged is probably obsolete [ Murphy, et al ].
- X
- X!SUBHED!Miscellany!ENDSUBHED!
- The remaining tests are in the miscellaneous group: Tower of Hanoi (a test of
- recursive operations) and a test of the UNIX arbitrary precision calculator
- calculating the square root of two to 99 decimal places.
- X No doubt, we will be adding tests to this suite as we see the need to test
- and evaluate from different perspectives.
- X
- X!SUBHED!Problems in the Modern World!ENDSUBHED!
- The major problem we have had with developing the UNIX benchmark programs is
- designing them so that they fairly reflect the strengths and weaknesses of
- all the systems on which we anticipate using them. For example, the
- operations should allow RISC machines to give appropriately high performance
- for the sorts of operations that RISC is good for, and should also illustrate
- improvements provided by faster bus speeds, better math coprocessors and the
- like. In the case of RISC, the efficiency of the compiler is of utmost
- importance; RISC compilers must rearrange instructions to take advantage of
- instruction pipelining (for an overview of RISC, see BYTE, May 1988).
- X The majority of the UNIX systems that we look at employ disk caching. This
- is especially important because modern UNIX includes swapping and paging out
- to disk when there is insufficient memory for a task or the number of tasks.
- It is an interesting exercise to run the disk file operations test with
- increasingly large files and note the point at which performance drops.
- X
- X!SUBHED!How They Work!ENDSUBHED!
- A 400 line Bourne shell script (!MONO!Run!ENDMONO!) administers the
- benchmarking system. After the evaluation of the command line options, the
- benchmarking operation for each test has three stages: parameter setup,
- timing the execution of the test, and calculation/formatting operations (see
- XFigure 1). After !MONO!Run!ENDMONO! determines the parameters for the test,
- it sends a formatted description to the output file. !MONO!Run!ENDMONO! then
- invokes the specific test by means of the UNIX command !MONO!time!ENDMONO!.
- The output of !MONO!time!ENDMONO! and any output from the test itself end up
- in a raw data file. Most tests are run six times so that any variance can be
- averaged. On completion of a set of tests, !MONO!Run!ENDMONO! invokes a
- cleanup script, which does the statistical calculations on the raw data using
- the !MONO!awk!ENDMONO! formatting language.
- X The greater part of the benchmark programs are written in C and are
- compiled on the test machine prior to running the tests.
- X
- X!SUBHED!Using the Results!ENDSUBHED!
- If all you need is a raw measure of performance, then feel free to use the
- Dhrystone and Whetstone tests as indices of just that. But if you want to use
- the benchmarks to evaluate a machine's ability to serve some real need, then
- you should do the following:
- X1. Analyze your requirements as far as the type of computing, amount and type
- of communications I/O, and amount and type of disk I/O.
- X2. Score the subject machines using weighting factors that reflect your
- requirements.
- X3. Generate a price vs. performance plot.
- X4. Use the price vs. performance, along with information about the
- reliability servicability of the hardware.
- X Step 4 is really more of an art than anything else. It is extremely
- important, however, to not rely on price vs. performance alone.
- X We use our UNIX Benchmarks for doing a rough analysis and comparison of
- divergent machines. (See figure 2, ``UNIX Machines Tested.'') As you can see,
- we even go so far as to generate a single index number, a sort of reduction
- of all of the benchmark tests to a single value. This index is generated by
- summing the the individual indices of the dhrystone test, the floating point
- test, the shell test with eight concurrent processes, the C compiler time,
- the !MONO!dc!ENDMONO! routine, and the tower of hanoi time. By definition,
- the combined index for the baseline machine is six. Indicess above six imply
- a better overall performance than the baseline machine; indices less than
- six, worse performance. Always keep in mind that having a single index rating
- for a machine may make good cocktail conversation, but it is incredibly
- simplistic. It is like reducing a complex sculptural shape to a single point;
- you no longer can tell what you are looking at. This number doesn't reflect
- any real-world use of a UNIX system. However, the index is devised so that it
- gives an overall indication of different kinds of system operations and so is
- valuable to our reviews.
- X BYTE's UNIX benchmarking suite is small enough to port easily to any UNIX
- system, yet diverse and flexible enough to be useful for a wide spectrum of
- benchmarking requirements. Besides, they're in the public domain, so they can
- be obtained for little, if any, cost. What better reason do you need to use
- them?
- END_OF_FILE
- if test 14682 -ne `wc -c <'doc/bench.doc'`; then
- echo shar: \"'doc/bench.doc'\" unpacked with wrong size!
- fi
- chmod +x 'doc/bench.doc'
- # end of 'doc/bench.doc'
- fi
- if test -f 'src/big.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/big.c'\"
- else
- echo shar: Extracting \"'src/big.c'\" \(13785 characters\)
- sed "s/^X//" >'src/big.c' <<'END_OF_FILE'
- X/*******************************************************************************
- X * The BYTE UNIX Benchmarks - Release 3
- X * Module: big.c SID: 3.3 5/15/91 19:30:18
- X *
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Ben Smith, Rick Grehan or Tom Yager
- X * ben@bytepb.byte.com rick_g@bytepb.byte.com tyager@bytepb.byte.com
- X *
- X *******************************************************************************
- X * Modification Log:
- X *
- X ******************************************************************************/
- X/*
- X * dummy code for execl test [ old version of makework.c ]
- X *
- X * makework [ -r rate ] [ -c copyfile ] nusers
- X *
- X * job streams are specified on standard input with lines of the form
- X * full_path_name_for_command [ options ] [ <standard_input_file ]
- X *
- X * "standard input" is send to all nuser instances of the commands in the
- X * job streams at a rate not in excess of "rate" characters per second
- X * per command
- X *
- X */
- X/* this code is included in other files and therefore has no SCCSid */
- X#include <stdio.h>
- X#include <signal.h>
- X
- X#define DEF_RATE 5.0
- X#define GRANULE 5
- X#define CHUNK 60
- X#define MAXCHILD 12
- X#define MAXWORK 10
- X
- float thres;
- float est_rate = DEF_RATE;
- int nusers; /* number of concurrent users to be simulated by
- X * this process */
- int firstuser; /* ordinal identification of first user for this
- X * process */
- int nwork = 0; /* number of job streams */
- int exit_status = 0; /* returned to parent */
- int sigpipe; /* pipe write error flag */
- X
- struct st_work {
- X char *cmd; /* name of command to run */
- X char **av; /* arguments to command */
- X char *input; /* standard input buffer */
- X int inpsize; /* size of standard input buffer */
- X char *outf; /* standard output (filename) */
- X} work[MAXWORK];
- X
- struct {
- X int xmit; /* # characters sent */
- X char *bp; /* std input buffer pointer */
- X int blen; /* std input buffer length */
- X int fd; /* stdin to command */
- X int pid; /* child PID */
- X char *line; /* start of input line */
- X int firstjob; /* inital piece of work */
- X int thisjob; /* current piece of work */
- X} child[MAXCHILD], *cp;
- X
- main(argc, argv)
- int argc;
- char *argv[];
- X{
- X int i;
- X int l;
- X int fcopy = 0; /* fd for copy output */
- X int master = 1; /* the REAL master, == 0 for clones */
- X int nchild; /* no. of children for a clone to run */
- X int done; /* count of children finished */
- X int output; /* aggregate output char count for all
- X children */
- X int c;
- X int thiswork = 0; /* next job stream to allocate */
- X int nch; /* # characters to write */
- X int written; /* # characters actully written */
- X char logname[15]; /* name of the log file(s) */
- X int onalarm();
- X int pipeerr();
- X int wrapup();
- X int grunt();
- X int pvec[2]; /* for pipes */
- X char *p;
- X char *prog; /* my name */
- X
- X#if ! debug
- X freopen("masterlog.00", "a", stderr);
- X#endif
- X fprintf(stderr, "*** New Run *** ");
- X prog = argv[0];
- X while (argc > 1 && argv[1][0] == '-') {
- X p = &argv[1][1];
- X argc--;
- X argv++;
- X while (*p) {
- X switch (*p) {
- X case 'r':
- X est_rate = atoi(argv[1]);
- X sscanf(argv[1], "%f", &est_rate);
- X if (est_rate <= 0) {
- X fprintf(stderr, "%s: bad rate, reset to %.2f chars/sec\n", prog, DEF_RATE);
- X est_rate = DEF_RATE;
- X }
- X argc--;
- X argv++;
- X break;
- X
- X case 'c':
- X fcopy = open(argv[1], 1);
- X if (fcopy < 0)
- X fcopy = creat(argv[1], 0600);
- X if (fcopy < 0) {
- X fprintf(stderr, "%s: cannot open copy file '%s'\n",
- X prog, argv[1]);
- X exit(2);
- X }
- X lseek(fcopy, 0L, 2); /* append at end of file */
- X argc--;
- X argv++;
- X break;
- X
- X default:
- X fprintf(stderr, "%s: bad flag '%c'\n", prog, *p);
- X exit(4);
- X }
- X p++;
- X }
- X }
- X
- X if (argc < 2) {
- X fprintf(stderr, "%s: missing nusers\n", prog);
- X exit(4);
- X }
- X
- X nusers = atoi(argv[1]);
- X if (nusers < 1) {
- X fprintf(stderr, "%s: impossible nusers (%d<-%s)\n", prog, nusers, argv[1]);
- X exit(4);
- X }
- X fprintf(stderr, "%d Users\n", nusers);
- X argc--;
- X argv++;
- X
- X /* build job streams */
- X getwork();
- X#if debug
- X dumpwork();
- X#endif
- X
- X /* clone copies of myself to run up to MAXCHILD jobs each */
- X firstuser = MAXCHILD;
- X fprintf(stderr, "master pid %d\n", getpid());
- X fflush(stderr);
- X while (nusers > MAXCHILD) {
- X fflush(stderr);
- X if (nusers >= 2*MAXCHILD)
- X /* the next clone must run MAXCHILD jobs */
- X nchild = MAXCHILD;
- X else
- X /* the next clone must run the leftover jobs */
- X nchild = nusers - MAXCHILD;
- X if ((l = fork()) == -1) {
- X /* fork failed */
- X fatal("** clone fork failed **\n");
- X goto bepatient;
- X } else if (l > 0) {
- X fprintf(stderr, "master clone pid %d\n", l);
- X /* I am the master with nchild fewer jobs to run */
- X nusers -= nchild;
- X firstuser += MAXCHILD;
- X continue;
- X } else {
- X /* I am a clone, run MAXCHILD jobs */
- X#if ! debug
- X sprintf(logname, "masterlog.%02d", firstuser/MAXCHILD);
- X freopen(logname, "w", stderr);
- X#endif
- X master = 0;
- X nusers = nchild;
- X break;
- X }
- X }
- X if (master)
- X firstuser = 0;
- X
- X close(0);
- X for (i = 0; i < nusers; i++ ) {
- X fprintf(stderr, "user %d job %d ", firstuser+i, thiswork);
- X if (pipe(pvec) == -1) {
- X /* this is fatal */
- X fatal("** pipe failed **\n");
- X goto bepatient;
- X }
- X fflush(stderr);
- X if ((child[i].pid = fork()) == 0) {
- X int fd;
- X /* the command */
- X if (pvec[0] != 0) {
- X close(0);
- X dup(pvec[0]);
- X }
- X#if ! debug
- X sprintf(logname, "userlog.%02d", firstuser+i);
- X freopen(logname, "w", stderr);
- X#endif
- X for (fd = 3; fd < 24; fd++)
- X close(fd);
- X if (work[thiswork].outf[0] != '\0') {
- X /* redirect std output */
- X char *q;
- X for (q = work[thiswork].outf; *q != '\n'; q++) ;
- X *q = '\0';
- X if (freopen(work[thiswork].outf, "w", stdout) == NULL) {
- X fprintf(stderr, "makework: cannot open %s for std output\n",
- X work[thiswork].outf);
- X fflush(stderr);
- X }
- X *q = '\n';
- X }
- X execv(work[thiswork].cmd, work[thiswork].av);
- X /* don't expect to get here! */
- X fatal("** exec failed **\n");
- X goto bepatient;
- X }
- X else if (child[i].pid == -1) {
- X fatal("** fork failed **\n");
- X goto bepatient;
- X }
- X else {
- X close(pvec[0]);
- X child[i].fd = pvec[1];
- X child[i].line = child[i].bp = work[thiswork].input;
- X child[i].blen = work[thiswork].inpsize;
- X child[i].thisjob = thiswork;
- X child[i].firstjob = thiswork;
- X fprintf(stderr, "pid %d pipe fd %d", child[i].pid, child[i].fd);
- X if (work[thiswork].outf[0] != '\0') {
- X char *q;
- X fprintf(stderr, " > ");
- X for (q=work[thiswork].outf; *q != '\n'; q++)
- X fputc(*q, stderr);
- X }
- X fputc('\n', stderr);
- X thiswork++;
- X if (thiswork >= nwork)
- X thiswork = 0;
- X }
- X }
- X fflush(stderr);
- X
- X srand(time(0));
- X thres = 0;
- X done = output = 0;
- X for (i = 0; i < nusers; i++) {
- X if (child[i].blen == 0)
- X done++;
- X else
- X thres += est_rate * GRANULE;
- X }
- X est_rate = thres;
- X
- X signal(SIGALRM, onalarm);
- X signal(SIGPIPE, pipeerr);
- X alarm(GRANULE);
- X while (done < nusers) {
- X for (i = 0; i < nusers; i++) {
- X cp = &child[i];
- X if (cp->xmit >= cp->blen) continue;
- X l = rand() % CHUNK + 1; /* 1-CHUNK chars */
- X if (l == 0) continue;
- X if (cp->xmit + l > cp->blen)
- X l = cp->blen - cp->xmit;
- X p = cp->bp;
- X cp->bp += l;
- X cp->xmit += l;
- X#if debug
- X fprintf(stderr, "child %d, %d processed, %d to go\n", i, cp->xmit, cp->blen - cp->xmit);
- X#endif
- X while (p < cp->bp) {
- X if (*p == '\n' || (p == &cp->bp[-1] && cp->xmit >= cp->blen)) {
- X /* write it out */
- X nch = p - cp->line + 1;
- X if ((written = write(cp->fd, cp->line, nch)) != nch) {
- X /* argh! */
- X cp->line[nch] = '\0';
- X fprintf(stderr, "user %d job %d cmd %s ",
- X firstuser+i, cp->thisjob, cp->line);
- X fprintf(stderr, "write(,,%d) returns %d\n", nch, written);
- X if (sigpipe)
- X fatal("** SIGPIPE error **\n");
- X else
- X fatal("** write error **\n");
- X goto bepatient;
- X
- X }
- X if (fcopy)
- X write(fcopy, cp->line, p - cp->line + 1);
- X#if debug
- X fprintf(stderr, "child %d gets \"", i);
- X {
- X char *q = cp->line;
- X while (q <= p) {
- X if (*q >= ' ' && *q <= '~')
- X fputc(*q, stderr);
- X else
- X fprintf(stderr, "\\%03o", *q);
- X q++;
- X }
- X }
- X fputc('"', stderr);
- X#endif
- X cp->line = &p[1];
- X }
- X p++;
- X }
- X if (cp->xmit >= cp->blen) {
- X done++;
- X close(cp->fd);
- X#if debug
- X fprintf(stderr, "child %d, close std input\n", i);
- X#endif
- X }
- X output += l;
- X }
- X while (output > thres) {
- X pause();
- X#if debug
- X fprintf(stderr, "after pause: output, thres, done %d %.2f %d\n", output, thres, done);
- X#endif
- X }
- X }
- X
- bepatient:
- X alarm(0);
- X/****
- X * If everything is going OK, we should simply be able to keep
- X * looping unitil 'wait' fails, however some descendent process may
- X * be in a state from which it can never exit, and so a timeout
- X * is used.
- X * 5 minutes should be ample, since the time to run all jobs is of
- X * the order of 5-10 minutes, however some machines are painfully slow,
- X * so the timeout has been set at 20 minutes (1200 seconds).
- X ****/
- X signal(SIGALRM, grunt);
- X alarm(1200);
- X while ((c = wait(&l)) != -1) {
- X for (i = 0; i < nusers; i++) {
- X if (c == child[i].pid) {
- X fprintf(stderr, "user %d job %d pid %d done", firstuser+i, child[i].thisjob, c);
- X if (l != 0) {
- X if (l & 0x7f)
- X fprintf(stderr, " status %d", l & 0x7f);
- X if (l & 0xff00)
- X fprintf(stderr, " exit code %d", (l>>8) & 0xff);
- X exit_status = 4;
- X }
- X fputc('\n', stderr);
- X c = child[i].pid = -1;
- X break;
- X }
- X }
- X if (c != -1) {
- X fprintf(stderr, "master clone done, pid %d ", c);
- X if (l != 0) {
- X if (l & 0x7f)
- X fprintf(stderr, " status %d", l & 0x7f);
- X if (l & 0xff00)
- X fprintf(stderr, " exit code %d", (l>>8) & 0xff);
- X exit_status = 4;
- X }
- X fputc('\n', stderr);
- X }
- X }
- X alarm(0);
- X wrapup("Finished waiting ...");
- X
- X
- X}
- X
- onalarm()
- X{
- X thres += est_rate;
- X signal(SIGALRM, onalarm);
- X alarm(GRANULE);
- X}
- X
- grunt()
- X{
- X /* timeout after label "bepatient" in main */
- X exit_status = 4;
- X wrapup("Timed out waiting for jobs to finish ...");
- X}
- X
- pipeerr()
- X{
- X sigpipe++;
- X}
- X
- wrapup(reason)
- char *reason;
- X{
- X int i;
- X int killed = 0;
- X fflush(stderr);
- X for (i = 0; i < nusers; i++) {
- X if (child[i].pid > 0 && kill(child[i].pid, SIGKILL) != -1) {
- X if (!killed) {
- X killed++;
- X fprintf(stderr, "%s\n", reason);
- X fflush(stderr);
- X }
- X fprintf(stderr, "user %d job %d pid %d killed off\n", firstuser+i, child[i].thisjob, child[i].pid);
- X fflush(stderr);
- X }
- X }
- X exit(exit_status);
- X}
- X
- getwork()
- X{
- X int i;
- X int f;
- X int ac;
- X char *lp;
- X char *q;
- X struct st_work *w;
- X char line[512];
- X char c;
- X char *malloc(), *realloc();
- X
- X while (gets(line) != NULL) {
- X if (nwork >= MAXWORK) {
- X fprintf(stderr, stderr, "Too many jobs specified, .. increase MAXWORK\n");
- X exit(4);
- X }
- X w = &work[nwork];
- X lp = line;
- X i = 1;
- X while (*lp && *lp != ' ') {
- X i++;
- X lp++;
- X }
- X w->cmd = (char *)malloc(i);
- X strncpy(w->cmd, line, i-1);
- X w->cmd[i-1] = '\0';
- X w->inpsize = 0;
- X w->input = "";
- X /* start to build arg list */
- X ac = 2;
- X w->av = (char **)malloc(2*sizeof(char *));
- X q = w->cmd;
- X while (*q) q++;
- X q--;
- X while (q >= w->cmd) {
- X if (*q == '/') {
- X q++;
- X break;
- X }
- X q--;
- X }
- X w->av[0] = q;
- X while (*lp) {
- X if (*lp == ' ') {
- X /* space */
- X lp++;
- X continue;
- X }
- X else if (*lp == '<') {
- X /* standard input for this job */
- X q = ++lp;
- X while (*lp && *lp != ' ') lp++;
- X c = *lp;
- X *lp = '\0';
- X if ((f = open(q, 0)) == -1) {
- X fprintf(stderr, "cannot open input file (%s) for job %d\n",
- X q, nwork);
- X exit(4);
- X }
- X /* gobble input */
- X w->input = (char *)malloc(512);
- X while ((i = read(f, &w->input[w->inpsize], 512)) > 0) {
- X w->inpsize += i;
- X w->input = (char *)realloc(w->input, w->inpsize+512);
- X }
- X w->input = (char *)realloc(w->input, w->inpsize);
- X close(f);
- X /* extract stdout file name from line beginning "C=" */
- X w->outf = "";
- X for (q = w->input; q < &w->input[w->inpsize-10]; q++) {
- X if (*q == '\n' && strncmp(&q[1], "C=", 2) == 0) {
- X w->outf = &q[3];
- X break;
- X }
- X }
- X#if debug
- X if (*w->outf) {
- X fprintf(stderr, "stdout->");
- X for (q=w->outf; *q != '\n'; q++)
- X fputc(*q, stderr);
- X fputc('\n', stderr);
- X }
- X#endif
- X }
- X else {
- X /* a command option */
- X ac++;
- X w->av = (char **)realloc(w->av, ac*sizeof(char *));
- X q = lp;
- X i = 1;
- X while (*lp && *lp != ' ') {
- X lp++;
- X i++;
- X }
- X w->av[ac-2] = (char *)malloc(i);
- X strncpy(w->av[ac-2], q, i-1);
- X w->av[ac-2][i-1] = '\0';
- X }
- X }
- X w->av[ac-1] = (char *)0;
- X nwork++;
- X }
- X}
- X
- X#if debug
- dumpwork()
- X{
- X int i;
- X int j;
- X
- X for (i = 0; i < nwork; i++) {
- X fprintf(stderr, "job %d: cmd: %s\n", i, work[i].cmd);
- X j = 0;
- X while (work[i].av[j]) {
- X fprintf(stderr, "argv[%d]: %s\n", j, work[i].av[j]);
- X j++;
- X }
- X fprintf(stderr, "input: %d chars text: ", work[i].inpsize);
- X if (work[i].input == (char *)0)
- X fprintf(stderr, "<NULL>\n");
- X else {
- X register char *pend;
- X char *p;
- X char c;
- X p = work[i].input;
- X while (*p) {
- X pend = p;
- X while (*pend && *pend != '\n')
- X pend++;
- X c = *pend;
- X *pend = '\0';
- X fprintf(stderr, "%s\n", p);
- X *pend = c;
- X p = &pend[1];
- X }
- X }
- X }
- X}
- X#endif
- X
- fatal(s)
- char *s;
- X{
- X int i;
- X fprintf(stderr, s);
- X fflush(stderr);
- X perror("Reason?");
- X fflush(stderr);
- X for (i = 0; i < nusers; i++) {
- X if (child[i].pid > 0 && kill(child[i].pid, SIGKILL) != -1) {
- X fprintf(stderr, "pid %d killed off\n", child[i].pid);
- X fflush(stderr);
- X }
- X }
- X exit_status = 4;
- X return;
- X}
- END_OF_FILE
- if test 13785 -ne `wc -c <'src/big.c'`; then
- echo shar: \"'src/big.c'\" unpacked with wrong size!
- fi
- chmod +x 'src/big.c'
- # end of 'src/big.c'
- fi
- if test -f 'src/dhry_1.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/dhry_1.c'\"
- else
- echo shar: Extracting \"'src/dhry_1.c'\" \(12970 characters\)
- sed "s/^X//" >'src/dhry_1.c' <<'END_OF_FILE'
- X/*****************************************************************************
- X * The BYTE UNIX Benchmarks - Release 3
- X * Module: dhry_1.c SID: 3.4 5/15/91 19:30:21
- X *
- X *****************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Ben Smith, Rick Grehan or Tom Yager
- X * ben@bytepb.byte.com rick_g@bytepb.byte.com tyager@bytepb.byte.com
- X *
- X *****************************************************************************
- X *
- X * *** WARNING **** With BYTE's modifications applied, results obtained with
- X * ******* this version of the Dhrystone program may not be applicable
- X * to other versions.
- X *
- X * Modification Log:
- X *
- X * Adapted from:
- X *
- X * "DHRYSTONE" Benchmark Program
- X * -----------------------------
- X *
- X * Version: C, Version 2.1
- X *
- X * File: dhry_1.c (part 2 of 3)
- X *
- X * Date: May 25, 1988
- X *
- X * Author: Reinhold P. Weicker
- X *
- X ***************************************************************************/
- char SCCSid[] = "@(#) @(#)dhry_1.c:3.4 -- 5/15/91 19:30:21";
- X
- X#include <stdio.h>
- X#include "dhry.h"
- X#include "timeit.c"
- X
- unsigned long Run_Index;
- X
- report()
- X{
- X fprintf(stderr,"%ld loops\n", Run_Index);
- X exit(0);
- X}
- X
- X/* Global Variables: */
- X
- Rec_Pointer Ptr_Glob,
- X Next_Ptr_Glob;
- int Int_Glob;
- Boolean Bool_Glob;
- char Ch_1_Glob,
- X Ch_2_Glob;
- int Arr_1_Glob [50];
- int Arr_2_Glob [50] [50];
- X
- extern char *malloc ();
- XEnumeration Func_1 ();
- X /* forward declaration necessary since Enumeration may not simply be int */
- X
- X#ifndef REG
- X Boolean Reg = false;
- X#define REG
- X /* REG becomes defined as empty */
- X /* i.e. no register variables */
- X#else
- X Boolean Reg = true;
- X#endif
- X
- X/* variables for time measurement: */
- X
- X#ifdef TIMES
- struct tms time_info;
- extern int times ();
- X /* see library function "times" */
- X#define Too_Small_Time 120
- X /* Measurements should last at least about 2 seconds */
- X#endif
- X#ifdef TIME
- extern long time();
- X /* see library function "time" */
- X#define Too_Small_Time 2
- X /* Measurements should last at least 2 seconds */
- X#endif
- X
- long Begin_Time,
- X End_Time,
- X User_Time;
- float Microseconds,
- X Dhrystones_Per_Second;
- X
- X/* end of variables for time measurement */
- X
- X
- main (argc, argv, env)
- int argc;
- char *argv[], *env[];
- X/*****/
- X
- X /* main program, corresponds to procedures */
- X /* Main and Proc_0 in the Ada version */
- X{
- X int duration;
- X One_Fifty Int_1_Loc;
- X REG One_Fifty Int_2_Loc;
- X One_Fifty Int_3_Loc;
- X REG char Ch_Index;
- X Enumeration Enum_Loc;
- X Str_30 Str_1_Loc;
- X Str_30 Str_2_Loc;
- X REG int Number_Of_Runs;
- X
- X /* Initializations */
- X
- X Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
- X Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
- X
- X Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
- X Ptr_Glob->Discr = Ident_1;
- X Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
- X Ptr_Glob->variant.var_1.Int_Comp = 40;
- X strcpy (Ptr_Glob->variant.var_1.Str_Comp,
- X "DHRYSTONE PROGRAM, SOME STRING");
- X strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
- X
- X Arr_2_Glob [8][7] = 10;
- X /* Was missing in published program. Without this statement, */
- X /* Arr_2_Glob [8][7] would have an undefined value. */
- X /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */
- X /* overflow may occur for this array element. */
- X
- X#ifdef PRATTLE
- X printf ("\n");
- X printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
- X printf ("\n");
- X if (Reg)
- X {
- X printf ("Program compiled with 'register' attribute\n");
- X printf ("\n");
- X }
- X else
- X {
- X printf ("Program compiled without 'register' attribute\n");
- X printf ("\n");
- X }
- X printf ("Please give the number of runs through the benchmark: ");
- X {
- X int n;
- X scanf ("%d", &n);
- X Number_Of_Runs = n;
- X }
- X printf ("\n");
- X
- X printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs);
- X#endif /* PRATTLE */
- X
- X if (argc != 2) {
- X printf("Usage: %s duration\n", argv[0]);
- X exit(1);
- X }
- X
- X duration = atoi(argv[1]);
- X Run_Index = 0;
- X wake_me(duration, report);
- X
- X /***************/
- X /* Start timer */
- X /***************/
- X
- X#ifdef SELF_TIMED
- X#ifdef TIMES
- X times (&time_info);
- X Begin_Time = (long) time_info.tms_utime;
- X#endif
- X#ifdef TIME
- X Begin_Time = time ( (long *) 0);
- X#endif
- X#endif /* SELF_TIMED */
- X
- X for (Run_Index = 1; ; ++Run_Index)
- X {
- X
- X Proc_5();
- X Proc_4();
- X /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
- X Int_1_Loc = 2;
- X Int_2_Loc = 3;
- X strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
- X Enum_Loc = Ident_2;
- X Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
- X /* Bool_Glob == 1 */
- X while (Int_1_Loc < Int_2_Loc) /* loop body executed once */
- X {
- X Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
- X /* Int_3_Loc == 7 */
- X Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
- X /* Int_3_Loc == 7 */
- X Int_1_Loc += 1;
- X } /* while */
- X /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
- X Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
- X /* Int_Glob == 5 */
- X Proc_1 (Ptr_Glob);
- X for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
- X /* loop body executed twice */
- X {
- X if (Enum_Loc == Func_1 (Ch_Index, 'C'))
- X /* then, not executed */
- X {
- X Proc_6 (Ident_1, &Enum_Loc);
- X strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
- X Int_2_Loc = Run_Index;
- X Int_Glob = Run_Index;
- X }
- X }
- X /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
- X Int_2_Loc = Int_2_Loc * Int_1_Loc;
- X Int_1_Loc = Int_2_Loc / Int_3_Loc;
- X Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
- X /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
- X Proc_2 (&Int_1_Loc);
- X /* Int_1_Loc == 5 */
- X
- X } /* loop "for Run_Index" */
- X
- X /**************/
- X /* Stop timer */
- X /**************/
- X#ifdef SELF_TIMED
- X#ifdef TIMES
- X times (&time_info);
- X End_Time = (long) time_info.tms_utime;
- X#endif
- X#ifdef TIME
- X End_Time = time ( (long *) 0);
- X#endif
- X#endif /* SELF_TIMED */
- X
- X /* BYTE version never executes this stuff */
- X#ifdef SELF_TIMED
- X printf ("Execution ends\n");
- X printf ("\n");
- X printf ("Final values of the variables used in the benchmark:\n");
- X printf ("\n");
- X printf ("Int_Glob: %d\n", Int_Glob);
- X printf (" should be: %d\n", 5);
- X printf ("Bool_Glob: %d\n", Bool_Glob);
- X printf (" should be: %d\n", 1);
- X printf ("Ch_1_Glob: %c\n", Ch_1_Glob);
- X printf (" should be: %c\n", 'A');
- X printf ("Ch_2_Glob: %c\n", Ch_2_Glob);
- X printf (" should be: %c\n", 'B');
- X printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]);
- X printf (" should be: %d\n", 7);
- X printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]);
- X printf (" should be: Number_Of_Runs + 10\n");
- X printf ("Ptr_Glob->\n");
- X printf (" Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp);
- X printf (" should be: (implementation-dependent)\n");
- X printf (" Discr: %d\n", Ptr_Glob->Discr);
- X printf (" should be: %d\n", 0);
- X printf (" Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp);
- X printf (" should be: %d\n", 2);
- X printf (" Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp);
- X printf (" should be: %d\n", 17);
- X printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp);
- X printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
- X printf ("Next_Ptr_Glob->\n");
- X printf (" Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp);
- X printf (" should be: (implementation-dependent), same as above\n");
- X printf (" Discr: %d\n", Next_Ptr_Glob->Discr);
- X printf (" should be: %d\n", 0);
- X printf (" Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp);
- X printf (" should be: %d\n", 1);
- X printf (" Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp);
- X printf (" should be: %d\n", 18);
- X printf (" Str_Comp: %s\n",
- X Next_Ptr_Glob->variant.var_1.Str_Comp);
- X printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
- X printf ("Int_1_Loc: %d\n", Int_1_Loc);
- X printf (" should be: %d\n", 5);
- X printf ("Int_2_Loc: %d\n", Int_2_Loc);
- X printf (" should be: %d\n", 13);
- X printf ("Int_3_Loc: %d\n", Int_3_Loc);
- X printf (" should be: %d\n", 7);
- X printf ("Enum_Loc: %d\n", Enum_Loc);
- X printf (" should be: %d\n", 1);
- X printf ("Str_1_Loc: %s\n", Str_1_Loc);
- X printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
- X printf ("Str_2_Loc: %s\n", Str_2_Loc);
- X printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
- X printf ("\n");
- X
- X User_Time = End_Time - Begin_Time;
- X
- X if (User_Time < Too_Small_Time)
- X {
- X printf ("Measured time too small to obtain meaningful results\n");
- X printf ("Please increase number of runs\n");
- X printf ("\n");
- X }
- X else
- X {
- X#ifdef TIME
- X Microseconds = (float) User_Time * Mic_secs_Per_Second
- X / (float) Number_Of_Runs;
- X Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time;
- X#else
- X Microseconds = (float) User_Time * Mic_secs_Per_Second
- X / ((float) HZ * ((float) Number_Of_Runs));
- X Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs)
- X / (float) User_Time;
- X#endif
- X printf ("Microseconds for one run through Dhrystone: ");
- X printf ("%6.1f \n", Microseconds);
- X printf ("Dhrystones per Second: ");
- X printf ("%6.1f \n", Dhrystones_Per_Second);
- X printf ("\n");
- X }
- X#endif /* SELF_TIMED */
- X}
- X
- X
- Proc_1 (Ptr_Val_Par)
- X/******************/
- X
- REG Rec_Pointer Ptr_Val_Par;
- X /* executed once */
- X{
- X REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
- X /* == Ptr_Glob_Next */
- X /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */
- X /* corresponds to "rename" in Ada, "with" in Pascal */
- X
- X structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob);
- X Ptr_Val_Par->variant.var_1.Int_Comp = 5;
- X Next_Record->variant.var_1.Int_Comp
- X = Ptr_Val_Par->variant.var_1.Int_Comp;
- X Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
- X Proc_3 (&Next_Record->Ptr_Comp);
- X /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp
- X == Ptr_Glob->Ptr_Comp */
- X if (Next_Record->Discr == Ident_1)
- X /* then, executed */
- X {
- X Next_Record->variant.var_1.Int_Comp = 6;
- X Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp,
- X &Next_Record->variant.var_1.Enum_Comp);
- X Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
- X Proc_7 (Next_Record->variant.var_1.Int_Comp, 10,
- X &Next_Record->variant.var_1.Int_Comp);
- X }
- X else /* not executed */
- X structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
- X} /* Proc_1 */
- X
- X
- Proc_2 (Int_Par_Ref)
- X/******************/
- X /* executed once */
- X /* *Int_Par_Ref == 1, becomes 4 */
- X
- One_Fifty *Int_Par_Ref;
- X{
- X One_Fifty Int_Loc;
- X Enumeration Enum_Loc;
- X
- X Int_Loc = *Int_Par_Ref + 10;
- X do /* executed once */
- X if (Ch_1_Glob == 'A')
- X /* then, executed */
- X {
- X Int_Loc -= 1;
- X *Int_Par_Ref = Int_Loc - Int_Glob;
- X Enum_Loc = Ident_1;
- X } /* if */
- X while (Enum_Loc != Ident_1); /* true */
- X} /* Proc_2 */
- X
- X
- Proc_3 (Ptr_Ref_Par)
- X/******************/
- X /* executed once */
- X /* Ptr_Ref_Par becomes Ptr_Glob */
- X
- Rec_Pointer *Ptr_Ref_Par;
- X
- X{
- X if (Ptr_Glob != Null)
- X /* then, executed */
- X *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
- X Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
- X} /* Proc_3 */
- X
- X
- Proc_4 () /* without parameters */
- X/*******/
- X /* executed once */
- X{
- X Boolean Bool_Loc;
- X
- X Bool_Loc = Ch_1_Glob == 'A';
- X Bool_Glob = Bool_Loc | Bool_Glob;
- X Ch_2_Glob = 'B';
- X} /* Proc_4 */
- X
- X
- Proc_5 () /* without parameters */
- X/*******/
- X /* executed once */
- X{
- X Ch_1_Glob = 'A';
- X Bool_Glob = false;
- X} /* Proc_5 */
- X
- X
- X /* Procedure for the assignment of structures, */
- X /* if the C compiler doesn't support this feature */
- X#ifdef NOSTRUCTASSIGN
- memcpy (d, s, l)
- register char *d;
- register char *s;
- register int l;
- X{
- X while (l--) *d++ = *s++;
- X}
- X#endif
- X
- X
- END_OF_FILE
- if test 12970 -ne `wc -c <'src/dhry_1.c'`; then
- echo shar: \"'src/dhry_1.c'\" unpacked with wrong size!
- fi
- chmod +x 'src/dhry_1.c'
- # end of 'src/dhry_1.c'
- fi
- echo shar: End of archive 3 \(of 4\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 4 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-