home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / byte-benchmarks3.1 / part03 < prev    next >
Encoding:
Text File  |  1992-02-01  |  57.6 KB  |  1,806 lines

  1. Newsgroups: comp.sources.unix
  2. From: ben@bytepb.byte.com (Ben Smith @ BYTE)
  3. Subject: v25i110: BYTE Benchmarks, V3.1, Part03/04
  4. Sender: sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: ben@bytepb.byte.com (Ben Smith @ BYTE)
  8. Posting-Number: Volume 25, Issue 110
  9. Archive-Name: byte-benchmarks3.1/part03
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 3 (of 4)."
  18. # Contents:  Run doc/bench.doc src/big.c src/dhry_1.c
  19. # Wrapped by vixie@cognition.pa.dec.com on Sun Feb  2 16:27:40 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'Run' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'Run'\"
  23. else
  24. echo shar: Extracting \"'Run'\" \(13305 characters\)
  25. sed "s/^X//" >'Run' <<'END_OF_FILE'
  26. X#! /bin/sh
  27. X#################### set your defaults here ##############
  28. XFLAVOR="" # flavor of UNIX: if not determined by script: SysV or BSD
  29. XFULL_SUITE="dhry2 dhry2reg arithoh register short int long float double syscall pipe context1 spawn execl fstime C shell dc hanoi"
  30. X###############################################################################
  31. X#  The BYTE UNIX Benchmarks - Release 3
  32. X#          Module: Run   SID: 3.11 5/15/91 19:30:14
  33. X#          
  34. X###############################################################################
  35. X# Bug reports, patches, comments, suggestions should be sent to:
  36. X#
  37. X#    Ben Smith,            Tom Yager at BYTE Magazine
  38. X#    ben@bytepb.byte.com       tyager@bytepb.byte.com
  39. X# BIX:  bensmith              tyager
  40. X#
  41. X###############################################################################
  42. X#  Modification Log:
  43. X# $Header: run,v 5.2 88/01/12 06:23:43 kenj Exp $
  44. X#     Ken McDonell, Computer Science, Monash University
  45. X#     August 1, 1983
  46. X# 3/89 - Ben Smith - BYTE: globalized many variables, modernized syntax
  47. X# 5/89 - commented and modernized. Removed workload items till they
  48. X#        have been modernized. Added database server test.
  49. X# 11/14/89 - Made modifications to reflect new version of fstime
  50. X#        and elimination of mem tests.
  51. X# 10/22/90 - Many tests have been flipped so that they run for
  52. X#        a specified length of time and loops are counted.
  53. X#  4/3/91 - Cleaned up and debugged several test parameters - Ben
  54. X#  4/9/91 - Added structure for creating index and determing flavor of UNIX
  55. X#  4/26/91 - Made changes and corrections suggested by Tin Le of Sony
  56. X#  5/15/91 - Removed db from distribution
  57. X#
  58. X###############################################################################
  59. ID="@(#)Run:3.11 -- 5/15/91 19:30:14";
  60. version="3.11"
  61. X#######################################################################
  62. X# General Purpose Benchmark
  63. X# based on the work by Ken McDonell, Computer Science, Monash University
  64. X#
  65. X#  You will need ...
  66. X#    awk cat cc chmod comm cp date dc df echo ed expr
  67. X#    kill ls make mkdir rm sed test time touch tty umask who
  68. X#       AND /bin/time
  69. X#  to generate result indexes, you will also need ...
  70. X#       join
  71. X#
  72. X#
  73. umask 022    # at least mortals can read root's files this way
  74. X#
  75. if [ -z "$FLAVOR" ]
  76. then
  77. X   # determine flavor of UNIX from number of lines generated by /bin/tim
  78. X   Fcount=`/bin/time date 2>&1 | wc -l | sed 's/ //g'`
  79. X   case "$Fcount"
  80. X   in
  81. X    2) FLAVOR="BSD";;
  82. X    5) FLAVOR="SysV";;
  83. X    *) echo "Flavor of UNIX is not known."
  84. X       echo "Please define FLAVOR in Run script"
  85. X       exit;;
  86. X   esac
  87. fi
  88. X#if SysV use 'uname -a' -- if BSD use 'hostname'
  89. if [ $FLAVOR = "SysV" ]
  90. then UNAME="uname -a"
  91. else UNAME="hostname"
  92. fi
  93. export FLAVOR
  94. X# check that the required files are in the proper places
  95. if make check 
  96. X        then :
  97. X        else make all
  98. fi
  99. X#
  100. X#
  101. X# establish full paths to directories
  102. PWD=`pwd`
  103. HOMEDIR=${HOMEDIR-.}
  104. cd $HOMEDIR
  105. HOMEDIR=`pwd`
  106. cd $PWD
  107. X
  108. BINDIR=${BINDIR-${HOMEDIR}/pgms}
  109. cd $BINDIR
  110. BINDIR=`pwd`
  111. cd $PWD
  112. X# let's extend the path to this directory
  113. PATH="${PATH}:${BINDIR}"
  114. X
  115. SCRPDIR=${SCRPDIR-${HOMEDIR}/pgms}
  116. cd $SCRPDIR
  117. SCRPDIR=`pwd`
  118. cd $PWD
  119. X
  120. TMPDIR=${HOMEDIR}/tmp
  121. cd $TMPDIR
  122. TMPDIR=`pwd`
  123. cd $PWD
  124. X
  125. RESULTDIR=${RESULTDIR-${HOMEDIR}/results}
  126. cd $RESULTDIR
  127. RESULTDIR=`pwd`
  128. cd $PWD
  129. X
  130. TIMEACCUM=${TIMEACCUM-${RESULTDIR}/times}
  131. X
  132. TESTDIR=${TESTDIR-${HOMEDIR}/testdir}
  133. cd $TESTDIR
  134. TESTDIR=`pwd`
  135. cd $PWD
  136. X
  137. export BINDIR TMPDIR RESULTDIR PATH TESTDIR TIMEACCUM
  138. X#
  139. cat ${BINDIR}/byte.logo # display banner
  140. rm -f ${TIMEACCUM}      # clean out old time accumulation file
  141. echo "kill -9 $$" > ${TMPDIR}/kill_run ; chmod u+x ${TMPDIR}/kill_run
  142. X#
  143. arithmetic="arithoh register short int long float double"
  144. system="syscall pipe context1 spawn execl fstime"
  145. misc="C dc hanoi"
  146. dhry="dhry2 dhry2reg" # dhrystone loops
  147. load="shell" # cummulative load tests
  148. index="double dhry2 execl fstime context1 shell"
  149. X#
  150. args="" # the accumulator for the bench units to be run
  151. runoption="N"
  152. X# generate list of bench programs
  153. for word
  154. do  # do level 1
  155. X    case $word
  156. X    in
  157. X  all)
  158. X      ;;
  159. X  arithmetic)
  160. X      args="$args $arithmetic"
  161. X      ;;
  162. X  dhry)
  163. X      args="$args $dhry"
  164. X      ;;
  165. X  load)
  166. X      args="$args $load"
  167. X      ;;
  168. X  misc)
  169. X      args="$args $misc"
  170. X      ;;
  171. X  speed)
  172. X      args="$args $arithmetic $system"
  173. X      ;;
  174. X  system)
  175. X      args="$args $system"
  176. X      ;;
  177. X  index)
  178. X      args="$args $index"
  179. X      ;;
  180. X  -q|-Q)
  181. X      runoption="Q" #quiet
  182. X      shift
  183. X      ;;
  184. X  -v|-V)
  185. X      runoption="V" #verbose
  186. X      shift
  187. X      ;;
  188. X  -d|-D)
  189. X      runoption="D" #debug
  190. X      shift
  191. X      ;;
  192. X  *)
  193. X      args="$args $word"
  194. X      ;;
  195. X    esac
  196. X
  197. done # end do level 1
  198. X#if no benchmark units have be specified, do them all 
  199. X# the - option of set implies no options; any list following
  200. X# becomes the line arguments (replacing any that may exist)
  201. set - $args
  202. if test $# -eq 0  #no arguments specified
  203. X   then
  204. X   set - $FULL_SUITE
  205. fi
  206. X
  207. if test "$runoption" = 'D'
  208. then
  209. X  set -x
  210. X  set -v
  211. fi
  212. X
  213. date=`date`
  214. TMPTIMES=${TMPDIR}/$$.tmp
  215. LOGFILE=${RESULTDIR}/log
  216. REPORTLOG=${RESULTDIR}/report
  217. X#add old log to accumulated log or move it
  218. if test -w ${RESULTDIR}/log
  219. then
  220. X   if test -w ${RESULTDIR}/log.accum
  221. X   then
  222. X      cat ${RESULTDIR}/log >> ${RESULTDIR}/log.accum
  223. X      rm ${RESULTDIR}/log
  224. X   else
  225. X      mv ${RESULTDIR}/log ${RESULTDIR}/log.accum
  226. X   fi
  227. fi
  228. echo "|  BYTE UNIX Benchmarks (Version $version)" >>$LOGFILE
  229. echo "|  System --" `$UNAME` >>$LOGFILE
  230. echo "|  Start Benchmark Run: `date`" >>$LOGFILE
  231. echo "|  " `who | wc -l` "interactive users." >>$LOGFILE
  232. X#if not specified, do each bench 6 iterations
  233. iter=${iterations-6}
  234. if test $iter -eq 6
  235. then
  236. X  longloop="1 2 3 4 5 6"
  237. X  shortloop="1 2 3"
  238. else  # generate list of loop numbers
  239. X  short=`expr \( $iter + 1 \) / 2`
  240. X  longloop=""
  241. X  shortloop=""
  242. X  while test $iter -gt 0
  243. X  do # do level 1
  244. X       longloop="$iter $longloop"
  245. X       if test $iter -le $short
  246. X       then
  247. X         shortloop="$iter $shortloop"
  248. X       fi
  249. X       iter=`expr $iter - 1`
  250. X  done # end do level 1
  251. fi #loop list genration
  252. X####################################################################
  253. X############## the major control loop ##############################
  254. X####################################################################
  255. for bench # line argument processing
  256. do # do level 1
  257. X    # set some default values
  258. X    prog=${BINDIR}/$bench  # the bench name is default program
  259. X    paramlist="#"          # a dummy parameter to make anything run
  260. X    testdir="${TESTDIR}"   # the directory in which to run the test
  261. X    prepcmd=""             # preparation command or script
  262. X    parammsg=""
  263. X    repeat="$longloop"
  264. X    stdout="$LOGFILE"
  265. X    stdin=""
  266. X    options=""
  267. X    logmsg=""
  268. X    cleanopt="-l $TMPTIMES"
  269. X    bgnumber=""
  270. X    trap "${SCRPDIR}/cleanup.sh -L $LOGFILE -a; exit" 1 2 3 15
  271. X    echo "" >>$LOGFILE
  272. X    ###################### select the bench specific values ##########
  273. X    case $bench
  274. X    in
  275. X  dhry2)
  276. X    options=${dhrytime-10}
  277. X    logmsg="Dhrystone 2 without register variables"
  278. X    ;;
  279. X
  280. X  dhry2reg)
  281. X    options=${dhrytime-10}
  282. X    logmsg="Dhrystone 2 using register variables"
  283. X    ;;
  284. X
  285. X  arithoh|register|short|int|long)
  286. X    options=${arithtime-10}
  287. X    logmsg="Arithmetic Test (type = $bench)"
  288. X    ;;
  289. X
  290. X  float|double)
  291. X    options=${arithtime-10}
  292. X    logmsg="Arithmetic Test (type = $bench)"
  293. X    ;;
  294. X
  295. X  syscall)
  296. X    options=${systime-10}
  297. X    logmsg="System Call Overhead Test"
  298. X    ;;
  299. X
  300. X  context1)
  301. X    options=${systime-10}
  302. X    logmsg="Pipe-based Context Switching Test"
  303. X    ;;
  304. X
  305. X  pipe)   
  306. X    options=${systime-10}
  307. X    logmsg="Pipe Throughput Test"
  308. X    ;;
  309. X
  310. X  spawn)  
  311. X    options=${systime-10}
  312. X    logmsg="Process Creation Test"
  313. X    ;;
  314. X
  315. X  execl)  
  316. X    options=${systime-10}
  317. X    logmsg="Execl Throughput Test"
  318. X    ;;
  319. X
  320. X  fstime) 
  321. X    logmsg='Filesystem Throughput Test ($param second test)'
  322. X    where=${where-${TMPDIR}}
  323. X    cleanopt="-f $TMPTIMES"
  324. X    options='$param '"$where"
  325. X    paramlist=${seconds-"10 30"}
  326. X    parammsg='Test Time: $param secs'
  327. X    ;;
  328. X
  329. X  C)  
  330. X    logmsg="C Compiler Test"
  331. X    prog="looper ${looper-60} cc cctest.c"
  332. X    stdout=/dev/null
  333. X    repeat="$shortloop"
  334. X    cleanopt="-m $TMPTIMES"
  335. X    rm -f ${TESTDIR}/cctest.o ${TESTDIR}/a.out
  336. X    ;;
  337. X
  338. X  shell)
  339. X    logmsg='Shell scripts ($param concurrent)'
  340. X    prog="looper ${looper-60} multi.sh"
  341. X    repeat="$shortloop"
  342. X    stdout=/dev/null
  343. X    paramlist=${background-"1 2 4 8 "}
  344. X    parammsg='$param concurrent background processes'
  345. X    bgnumber='$param'
  346. X    cleanopt="-m $TMPTIMES"
  347. X    ;;
  348. X
  349. X  dc)  
  350. X    logmsg="Dc: sqrt(2) to 99 decimal places"
  351. X    prog="looper ${looper-60} dc"
  352. X    stdin=dc.dat
  353. X    stdout=/dev/null
  354. X    cleanopt="-m $TMPTIMES"
  355. X    ;;
  356. X
  357. X  hanoi)  
  358. X    options=${systime-10}
  359. X    stdout=/dev/null
  360. X    logmsg="Recursion Test--Tower of Hanoi"
  361. X    parammsg='$param Disk Problem:'
  362. X    ;;
  363. X
  364. X  *)   ${BINDIR}/cleanup.sh -L $LOGFILE -r "run: unknown benchmark \"$bench\" \n Known benchmarks are: \n $FULL_SUITE" -a
  365. X    exit 1
  366. X    ;;
  367. esac
  368. X################################################################
  369. X###################### the main task ###########################
  370. X###################### run the bench ###########################
  371. X################################################################
  372. X# each of those variables are now used in a general way
  373. X#
  374. X    for param in $paramlist
  375. X    do   # level 2
  376. X      param=`echo $param | sed 's/_/ /g'` # be sure that spaces are used
  377. X      eval Lmsg='"'$logmsg'"'
  378. X      eval opt='"'$options'"'         # evaluate any vars in options
  379. X      eval prep='"'$prepcmd'"'         # evaluate any prep command
  380. X      eval bg='"'$bgnumber'"'         # evaluate bgnumber string
  381. X      rm -f $TMPTIMES             # remove any tmp files
  382. X
  383. X      # if the test requires mulitple concurrent processes,
  384. X      # prepare the background process string (bgstr)
  385. X      # this is just a string of "+"s that will provides a
  386. X      # parameter count for a "for" loop
  387. X      bgstr=""
  388. X      if test "$bg" != ""
  389. X      then
  390. X      count=`expr "$bg"`
  391. X          while test $count -gt 0
  392. X          do
  393. X          bgstr="+ $bgstr"
  394. X          count=`expr $count - 1`
  395. X      done
  396. X      fi
  397. X      #
  398. X      echo "TEST|$Lmsg" >>$TMPTIMES
  399. X      echo "FLAVOR|${FLAVOR}" >>$TMPTIMES
  400. X      if [ "$runoption" != 'Q' ]
  401. X      then
  402. X          echo ""
  403. X          if [ $FLAVOR = "SysV" ]
  404. X         then echo "$Lmsg \c"
  405. X         else echo -n "$Lmsg "
  406. X          fi
  407. X    
  408. X      fi
  409. X      for i in $repeat             # loop for the specified number
  410. X      do  # do depth 3
  411. X          if [ "$runoption" != 'D' ]  # level 1
  412. X      then
  413. X        # regular Run - set logfile to go on signal
  414. X            trap "${BINDIR}/cleanup.sh -L $LOGFILE -i $i $cleanopt -a; exit" 1 2 3 15
  415. X      else
  416. X            trap "exit" 1 2 3 15
  417. X      fi #end level 1
  418. X      # make an attempt to flush buffers
  419. X      sync; sync; sleep 10
  420. X      # display heartbeat
  421. X          if [ "$runoption" != 'Q' ]
  422. X      then
  423. X          if [ $FLAVOR = "SysV" ]
  424. X             then echo " $i\c"      # display repeat number
  425. X             else echo -n " $i"
  426. X          fi
  427. X      fi
  428. X      pwd=`pwd`                     # remember where we are
  429. X      cd $testdir                   # move to the test directory
  430. X      if [ "$runoption" = "V" ]
  431. X      then
  432. X        echo
  433. X        echo "BENCH COMMAND TO BE EXECUTED:"
  434. X        echo "$prog $opt"
  435. X      fi
  436. X
  437. X      # execute any prepratory command string
  438. X      if [ -n "$prep" ]
  439. X      then
  440. X        $prep 2>&1 >>$stdout 
  441. X      fi
  442. X      ############ THE BENCH IS TIMED ##############
  443. X          if test "$stdin" = ""  
  444. X          then # without redirected stdin
  445. X             /bin/time $prog $opt $bgstr 2>>$TMPTIMES >>$stdout
  446. X          else # with redirected stdin
  447. X             /bin/time $prog $opt $bgstr <$stdin 2>>$TMPTIMES >>$stdout
  448. X          fi 
  449. X      /bin/time $benchcmd
  450. X      ###############################################
  451. X      cd $pwd                    # move back home
  452. X          status=$?                  # save the result code
  453. X          if test $status != 0 # must have been an error
  454. X          then
  455. X           if test -f $TMPTIMES # is there an error file ?
  456. X           then
  457. X                cp $TMPTIMES ${TMPDIR}/save.$bench.$param
  458. X            ${SCRPDIR}/cleanup.sh -L $LOGFILE -i $i $cleanopt -r \
  459. X           "run: bench=$bench param=$param fatalstatus=$status" -a
  460. X           else
  461. X            ${SCRPDIR}/cleanup.sh -L $LOGFILE -r \
  462. X           "run: bench=$bench param=$param fatalstatus=$status" -a
  463. X           fi 
  464. X           exit # leave the script if there are errors
  465. X          fi # end  level 1
  466. X      done # end do depth 3 - repeat of bench
  467. X      if [ "$runoption" != 'D' ]
  468. X      then
  469. X        ${SCRPDIR}/cleanup.sh -L $LOGFILE $cleanopt # finalize this bench
  470. X                         # with these options
  471. X                         # & calculate results
  472. X      fi
  473. X    done # end do depth 2 - end of all options for this bench
  474. X
  475. X    ########### some specific cleanup routines ##############
  476. X    case $bench
  477. X    in
  478. X      C)
  479. X      rm -f ${TESTDIR}/cctest.o ${TESTDIR}/a.out
  480. X      ;;
  481. X
  482. X      fstime)
  483. X      sync; sleep 20
  484. X      ;;
  485. X    esac
  486. X    if [ "$runoption" != 'Q' ]
  487. X    then
  488. X       echo ""
  489. X    fi
  490. done # end do level 1  - all benchmarks requested
  491. X########## a few last items for the end ##############
  492. echo "" >>$LOGFILE
  493. echo "End Benchmark Run: `date`" >>$LOGFILE
  494. echo " " `who | wc -l` "interactive users." >>$LOGFILE
  495. X# create the report
  496. X${SCRPDIR}/report.sh $LOGFILE > $REPORTLOG 
  497. X${SCRPDIR}/index.sh ${SCRPDIR}/index.base $LOGFILE >> $REPORTLOG
  498. if [ "$runoption" != 'Q' ]
  499. then
  500. X  echo ""
  501. X  echo "=============================================================="
  502. X  cat $REPORTLOG
  503. fi
  504. X
  505. exit
  506. X########################### Amen ######################
  507. END_OF_FILE
  508. if test 13305 -ne `wc -c <'Run'`; then
  509.     echo shar: \"'Run'\" unpacked with wrong size!
  510. fi
  511. chmod +x 'Run'
  512. # end of 'Run'
  513. fi
  514. if test -f 'doc/bench.doc' -a "${1}" != "-c" ; then 
  515.   echo shar: Will not clobber existing file \"'doc/bench.doc'\"
  516. else
  517. echo shar: Extracting \"'doc/bench.doc'\" \(14682 characters\)
  518. sed "s/^X//" >'doc/bench.doc' <<'END_OF_FILE'
  519. X@BT
  520. X
  521. X[TITLE]BYTE's UNIX Benchmarks
  522. X[DEK]Separating fact from fiction in the exploding UNIX empire
  523. X[TOC]Before you jump into the UNIX pool, see how your favorite system stacks
  524. up against the rest of the pack.
  525. X
  526. Ben Smith
  527. X
  528. In making purchase decisions, it's difficult to know whom to believe. Each
  529. vendor claims, predictably, that their products are better than the
  530. competition's, but how does one prove, or debunk, these claims?
  531. X  Cost and performance typically top the list of considerations for those
  532. seeking to purchase equipment, and while cost can be easily compared,
  533. performance cannot, and comparing costs without analyzing each system's
  534. relative value is a worthless exercise.
  535. X  When DOS became popular, it allowed for the development of performance
  536. measurement programs, benchmarks, that would run on any system that ran DOS.
  537. BYTE's lab technicians set about creating their own, and the BYTE DOS
  538. benchmarks were born. Dozens of systems have been clocked using these
  539. facilities, and each review of a new DOS-based system includes the results of
  540. these benchmarks.
  541. X  This is all very well, but while DOS is installed on a great many systems,
  542. it is no longer the !ITAL!only!ENDITAL! popular multi-platform operating
  543. system. User demands for greater expandability, better performance and
  544. multi-tasking have turned UNIX systems into one of the fastest growing
  545. segments of the market. When UNIX stepped from minicomputers to workstations,
  546. it established itself as the defacto OS for an exciting new breed of machine.
  547. Now, with solid implementations for affordable Intel and Motorola-based
  548. platforms, UNIX is making a name for itself in the PC realm. As UNIX finds
  549. its way into the mainstream, it is necessary to have the tools to objectively
  550. measure not only the performance of various hardware platforms, but of
  551. different versions of UNIX as well.
  552. X
  553. X!SUBHED!Unix is Not MS-DOS!ENDSUBHED!
  554. Conceptually, BYTE's UNIX benchmarks are the same as BYTE's MS-DOS
  555. benchmarks: We have combined evaluation of both low-level operations and
  556. high-level applications type programs to highlight the performance of the
  557. entire system.
  558. X  But UNIX is considerably different from MS-DOS. In the first place, it is a
  559. X!ITAL!multi!ENDITAL!-tasking, !ITAL!multi!ENDITAL!-user operating system. It
  560. is also portable, able to run on many different kinds of computers. MS-DOS is
  561. a !ITAL!single!ENDITAL!-tasking, !ITAL!single!ENDITAL!-user operating system,
  562. and it is intended to run on essentially one kind of computer, an IBM-PC or
  563. PC ``clone,'' utilizing a specific class of processor from Intel. As a
  564. result, the UNIX benchmarks differ from their MS-DOS counterparts. Even
  565. though there are some equivalent low-level tests, you will find that even
  566. these run differently; the popular Dhrystone benchmark commonly gives
  567. different results, on the same hardware, when run under both DOS and UNIX.
  568. The reason? Different compilers are being used, and the underlying operating
  569. systems and services are wildly different.
  570. X  Another important difference is that Microsoft is the only real source of
  571. DOS; other suppliers simply repackage Microsoft's basic operating system
  572. under other names. In contrast, there are many different kinds of UNIX, and
  573. while similarities exist (the core UNIX from Dell, Everex and Interactive
  574. Systems are virtually the same), there are UNIX and UNIX-like operating
  575. systems that differ greatly from one another. Conclusion: The UNIX benchmarks
  576. are evaluating the implementation of UNIX and the resident compiler as well
  577. as the hardware on which it is running (the MS-DOS and Apple Macintosh
  578. benchmarks use a common compiler, the public-domain Small C).
  579. X  With so many variables, what is constant? Well, we have established a
  580. baseline, SCO Xenix 386 version 2.3.1. running on the Everex 386/33 with 4
  581. Mbytes of RAM and an 80387 math coprocessor. While it isn't UNIX per se
  582. X(because AT&T decides which implementations may be called ``UNIX''), it is
  583. more popular than any other PC UNIX implementation. It is specifically
  584. designed for 80386-based computers with full 32 bit memory access. The Everex
  585. X386/33 was chosen because it is one of today's highest performance 386
  586. computers properly configured to run the full 32 bit operating system. (Some
  587. X386 computers cannot access memory through single 32 bit operations; small
  588. matter if you are just running MS-DOS, an 8 bit operating system, but serious
  589. if you want to run UNIX.) This combination of system and OS is timely, but
  590. we'll continue to adjust the baseline as needed to reflect the installed PC
  591. and workstation UNIX base.
  592. X
  593. X!SUBHED!The Low Level Bench Programs!ENDSUBHED!
  594. The BYTE UNIX benchmarks consist of eight groups of programs: arithmetic,
  595. system calls, memory operations, disk operations, dhrystone, database
  596. operations, system loading, and miscellaneous. These can be roughly divided
  597. into the low-level tests (arithmetic, system calls, memory, disk, and
  598. dhrystone) and high-level tests (database operations, system loading, and the
  599. C-compiler test that is part of the miscellaneous set).
  600. X  The Dhrystone test is known more formally as ``Dhrystone 2''. It performs
  601. no floating-point operations, but it does involve arrays, character strings,
  602. indirect addressing, and most of the non-floating point instructions that
  603. might be found in an application program. It also includes conditional
  604. operations and other common program flow controls. The output of the test is
  605. the number of dhrystone loops per second. It is used in the BYTE benchmarks
  606. because of its wide selection of operations and because it is one of the most
  607. widely run benchmark programs.
  608. X  A future version of the BYTE UNIX benchmarks will include the Whetstone
  609. benchmark test program, as well. The Whetstone benchmark is conceptually
  610. similar to the Dhrystone, but with an emphasis on math; it is a mix of
  611. floating point and integer arithmetic, function calls, array operations,
  612. conditionals, and transcendental function calls.
  613. X  All the arithmetic tests have the same source code with different data
  614. types substituted for the operations: register, short, int, long, float,
  615. double, and an empty loop for calculating the overhead required by the
  616. program. The actual test involves assignment, addition, subtraction,
  617. multiplication, and division. Very simple. But don't bother running the float
  618. and double precision test unless you have a math co-processor; what takes a
  619. math co-processor system 15 seconds, may take an unaided processor 30 minutes
  620. or more!
  621. X  The system call tests are: system call overhead, pipe throughput, pipe
  622. context switching, spawning of child processes, execl (replacement of the
  623. current process by a new process), and file read, write, and copy. The system
  624. call overhead test evaluates the time required to do iterations of
  625. X!MONO!dup()!ENDMONO!, !MONO!close()!ENDMONO!, !MONO!getpid()!ENDMONO!,
  626. X!MONO!getuid()!ENDMONO!, and !MONO!umask()!ENDMONO! calls.
  627. X  The pipe throughput test has no real counterpart in real-world programming;
  628. in it, a single process opens a pipe (an inter-process communications channel
  629. that works rather like its plumbing namesake) to itself and spins a megabyte
  630. around this short loop. You might call this the pipe overhead test. The
  631. context switching pipe test is more like a real-world application; the test
  632. program spawns a child process with which it carries on a bi-directional pipe
  633. conversation.
  634. X  The spawn test creates a child process which immediately dies after its own
  635. X!MONO!fork()!ENDMONO!. The process is repeated over and over. Similarly, the
  636. exec test is a process that repeatedly changes to a new incarnation. One of
  637. the arguments passed to the new incarnation is the number of remaining
  638. iterations (there has to be some control, after all).
  639. X The file read, write, and copy tests capture the number of characters that
  640. can be written, read, and copied in a specified time (default is 10 seconds).
  641. If you run this test with the minimum element (1 second), you should see a
  642. significantly higher value for all operations if your system implements disk
  643. cacheing. Be sure you have plenty of disk space before you run this test.
  644. X
  645. X!SUBHED!The High-Level Bench Programs!ENDSUBHED!
  646. To qualify as a high-level test, the test must involve operations that a
  647. real-world application program might employ, including heavy use of the CPU
  648. and disk. At the time of writing this article, we have currently implemented
  649. only the system loading and database tests, but we will be adding several new
  650. tests in the months ahead.
  651. X  The system loading test is a shell script that is run by 1, 2, 4, and 8
  652. concurrent processes. The script consists of an alphabetic sort one file to
  653. another; taking the octal dump of the result and doing a numeric sort to a
  654. third file; running grep on the result of the alphabetic sort file;
  655. X!MONO!tee!ENDMONO!ing the result to a file and to !MONO!wc!ENDMONO! (word
  656. count); writing the final result to a file; and removing all of the resulting
  657. files. This script was used in the original BYTE UNIX benchmarks (1983), but
  658. the source file is several magnitudes larger than the original.
  659. X  The C compile and link is nothing more than that.
  660. X  The database operations consist of random read, write, and add operations
  661. on a database file. The operations are handled by a server process; the
  662. requests come from client processes. The test is run with 1, 2, 4, and 8
  663. client processes. The test employs semaphores and message queues. Semaphores
  664. are being used less and less these days. BSD systems use sockets instead in
  665. place of both of these System V.3 IPC utilities. System V.4 offers both. This
  666. test is being rewritten using sockets, but since Xenix doesn't implement
  667. sockets, our baseline configuration becomes instantly obsolete when we
  668. replace the database test. Just another one of those little problems in
  669. trying to create journalistic computer benchmarks: any program that has been
  670. fully debugged is probably obsolete [ Murphy, et al ].
  671. X
  672. X!SUBHED!Miscellany!ENDSUBHED!
  673. The remaining tests are in the miscellaneous group: Tower of Hanoi (a test of
  674. recursive operations) and a test of the UNIX arbitrary precision calculator
  675. calculating the square root of two to 99 decimal places.
  676. X  No doubt, we will be adding tests to this suite as we see the need to test
  677. and evaluate from different perspectives.
  678. X
  679. X!SUBHED!Problems in the Modern World!ENDSUBHED!
  680. The major problem we have had with developing the UNIX benchmark programs is
  681. designing them so that they fairly reflect the strengths and weaknesses of
  682. all the systems on which we anticipate using them. For example, the
  683. operations should allow RISC machines to give appropriately high performance
  684. for the sorts of operations that RISC is good for, and should also illustrate
  685. improvements provided by faster bus speeds, better math coprocessors and the
  686. like. In the case of RISC, the efficiency of the compiler is of utmost
  687. importance; RISC compilers must rearrange instructions to take advantage of
  688. instruction pipelining (for an overview of RISC, see BYTE, May 1988).
  689. X  The majority of the UNIX systems that we look at employ disk caching. This
  690. is especially important because modern UNIX includes swapping and paging out
  691. to disk when there is insufficient memory for a task or the number of tasks.
  692. It is an interesting exercise to run the disk file operations test with
  693. increasingly large files and note the point at which performance drops.
  694. X
  695. X!SUBHED!How They Work!ENDSUBHED!
  696. A 400 line Bourne shell script (!MONO!Run!ENDMONO!) administers the
  697. benchmarking system. After the evaluation of the command line options, the
  698. benchmarking operation for each test has three stages: parameter setup,
  699. timing the execution of the test, and calculation/formatting operations (see
  700. XFigure 1). After !MONO!Run!ENDMONO! determines the parameters for the test,
  701. it sends a formatted description to the output file. !MONO!Run!ENDMONO! then
  702. invokes the specific test by means of the UNIX command !MONO!time!ENDMONO!.
  703. The output of !MONO!time!ENDMONO! and any output from the test itself end up
  704. in a raw data file. Most tests are run six times so that any variance can be
  705. averaged. On completion of a set of tests, !MONO!Run!ENDMONO! invokes a
  706. cleanup script, which does the statistical calculations on the raw data using
  707. the !MONO!awk!ENDMONO! formatting language.
  708. X  The greater part of the benchmark programs are written in C and are
  709. compiled on the test machine prior to running the tests. 
  710. X
  711. X!SUBHED!Using the Results!ENDSUBHED!
  712. If all you need is a raw measure of performance, then feel free to use the
  713. Dhrystone and Whetstone tests as indices of just that. But if you want to use
  714. the benchmarks to evaluate a machine's ability to serve some real need, then
  715. you should do the following:
  716. X1. Analyze your requirements as far as the type of computing, amount and type
  717. of communications I/O, and amount and type of disk I/O.
  718. X2. Score the subject machines using weighting factors that reflect your
  719. requirements.
  720. X3. Generate a price vs. performance plot.
  721. X4. Use the price vs. performance, along with information about the
  722. reliability servicability of the hardware.
  723. X  Step 4 is really more of an art than anything else. It is extremely
  724. important, however, to not rely on price vs. performance alone.
  725. X We use our UNIX Benchmarks for doing a rough analysis and comparison of
  726. divergent machines. (See figure 2, ``UNIX Machines Tested.'') As you can see,
  727. we even go so far as to generate a single index number, a sort of reduction
  728. of all of the benchmark tests to a single value. This index is generated by
  729. summing the the individual indices of the dhrystone test, the floating point
  730. test, the shell test with eight concurrent processes, the C compiler time,
  731. the !MONO!dc!ENDMONO! routine, and the tower of hanoi time. By definition,
  732. the combined index for the baseline machine is six. Indicess above six imply
  733. a better overall performance than the baseline machine; indices less than
  734. six, worse performance. Always keep in mind that having a single index rating
  735. for a machine may make good cocktail conversation, but it is incredibly
  736. simplistic. It is like reducing a complex sculptural shape to a single point;
  737. you no longer can tell what you are looking at. This number doesn't reflect
  738. any real-world use of a UNIX system. However, the index is devised so that it
  739. gives an overall indication of different kinds of system operations and so is
  740. valuable to our reviews.
  741. X  BYTE's UNIX benchmarking suite is small enough to port easily to any UNIX
  742. system, yet diverse and flexible enough to be useful for a wide spectrum of
  743. benchmarking requirements. Besides, they're in the public domain, so they can
  744. be obtained for little, if any, cost. What better reason do you need to use
  745. them?
  746. END_OF_FILE
  747. if test 14682 -ne `wc -c <'doc/bench.doc'`; then
  748.     echo shar: \"'doc/bench.doc'\" unpacked with wrong size!
  749. fi
  750. chmod +x 'doc/bench.doc'
  751. # end of 'doc/bench.doc'
  752. fi
  753. if test -f 'src/big.c' -a "${1}" != "-c" ; then 
  754.   echo shar: Will not clobber existing file \"'src/big.c'\"
  755. else
  756. echo shar: Extracting \"'src/big.c'\" \(13785 characters\)
  757. sed "s/^X//" >'src/big.c' <<'END_OF_FILE'
  758. X/*******************************************************************************
  759. X *  The BYTE UNIX Benchmarks - Release 3
  760. X *          Module: big.c   SID: 3.3 5/15/91 19:30:18
  761. X *          
  762. X *******************************************************************************
  763. X * Bug reports, patches, comments, suggestions should be sent to:
  764. X *
  765. X *    Ben Smith, Rick Grehan or Tom Yager
  766. X *    ben@bytepb.byte.com   rick_g@bytepb.byte.com   tyager@bytepb.byte.com
  767. X *
  768. X *******************************************************************************
  769. X *  Modification Log:
  770. X *
  771. X ******************************************************************************/
  772. X/*
  773. X *  dummy code for execl test [ old version of makework.c ]
  774. X *
  775. X *  makework [ -r rate ] [ -c copyfile ] nusers
  776. X *
  777. X *  job streams are specified on standard input with lines of the form
  778. X *  full_path_name_for_command [ options ] [ <standard_input_file ]
  779. X *
  780. X *  "standard input" is send to all nuser instances of the commands in the
  781. X *  job streams at a rate not in excess of "rate" characters per second
  782. X *  per command
  783. X *
  784. X */
  785. X/* this code is included in other files and therefore has no SCCSid */
  786. X#include <stdio.h>
  787. X#include <signal.h>
  788. X
  789. X#define DEF_RATE    5.0
  790. X#define GRANULE        5
  791. X#define CHUNK        60
  792. X#define MAXCHILD    12
  793. X#define MAXWORK        10
  794. X
  795. float    thres;
  796. float    est_rate = DEF_RATE;
  797. int    nusers;        /* number of concurrent users to be simulated by
  798. X             * this process */
  799. int    firstuser;    /* ordinal identification of first user for this
  800. X             * process */
  801. int    nwork = 0;    /* number of job streams */
  802. int    exit_status = 0;    /* returned to parent */
  803. int    sigpipe;    /* pipe write error flag */
  804. X
  805. struct st_work {
  806. X    char    *cmd;        /* name of command to run */
  807. X    char    **av;        /* arguments to command */
  808. X    char    *input;        /* standard input buffer */
  809. X    int    inpsize;    /* size of standard input buffer */
  810. X    char    *outf;        /* standard output (filename) */
  811. X} work[MAXWORK];
  812. X
  813. struct {
  814. X    int    xmit;    /* # characters sent */
  815. X    char    *bp;    /* std input buffer pointer */
  816. X    int    blen;    /* std input buffer length */
  817. X    int    fd;    /* stdin to command */
  818. X    int    pid;    /* child PID */
  819. X    char    *line;    /* start of input line */ 
  820. X    int    firstjob;    /* inital piece of work */
  821. X    int    thisjob;    /* current piece of work */
  822. X} child[MAXCHILD], *cp;
  823. X
  824. main(argc, argv)
  825. int    argc;
  826. char    *argv[];
  827. X{
  828. X    int        i;
  829. X    int        l;
  830. X    int        fcopy = 0;    /* fd for copy output */
  831. X    int        master = 1;    /* the REAL master, == 0 for clones */
  832. X    int        nchild;        /* no. of children for a clone to run */
  833. X    int        done;        /* count of children finished */
  834. X    int        output;        /* aggregate output char count for all
  835. X                   children */
  836. X    int        c;
  837. X    int        thiswork = 0;    /* next job stream to allocate */
  838. X    int        nch;        /* # characters to write */
  839. X    int        written;    /* # characters actully written */
  840. X    char    logname[15];    /* name of the log file(s) */
  841. X    int        onalarm();
  842. X    int        pipeerr();
  843. X    int        wrapup();
  844. X    int        grunt();
  845. X    int        pvec[2];    /* for pipes */
  846. X    char    *p;
  847. X    char    *prog;        /* my name */
  848. X
  849. X#if ! debug
  850. X    freopen("masterlog.00", "a", stderr);
  851. X#endif
  852. X    fprintf(stderr, "*** New Run ***  ");
  853. X    prog = argv[0];
  854. X    while (argc > 1 && argv[1][0] == '-')  {
  855. X    p = &argv[1][1];
  856. X    argc--;
  857. X    argv++;
  858. X    while (*p) {
  859. X        switch (*p) {
  860. X        case 'r':
  861. X            est_rate = atoi(argv[1]);
  862. X            sscanf(argv[1], "%f", &est_rate);
  863. X            if (est_rate <= 0) {
  864. X                fprintf(stderr, "%s: bad rate, reset to %.2f chars/sec\n", prog, DEF_RATE);
  865. X                est_rate = DEF_RATE;
  866. X            }
  867. X            argc--;
  868. X            argv++;
  869. X            break;
  870. X
  871. X        case 'c':
  872. X            fcopy = open(argv[1], 1);
  873. X            if (fcopy < 0)
  874. X                fcopy = creat(argv[1], 0600);
  875. X            if (fcopy < 0) {
  876. X                fprintf(stderr, "%s: cannot open copy file '%s'\n",
  877. X                prog, argv[1]);
  878. X                exit(2);
  879. X            }
  880. X            lseek(fcopy, 0L, 2);    /* append at end of file */
  881. X            argc--;
  882. X            argv++;
  883. X            break;
  884. X
  885. X        default:
  886. X        fprintf(stderr, "%s: bad flag '%c'\n", prog, *p);
  887. X            exit(4);
  888. X        }
  889. X        p++;
  890. X    }
  891. X    }
  892. X    
  893. X    if (argc < 2) {
  894. X    fprintf(stderr, "%s: missing nusers\n", prog);
  895. X    exit(4);
  896. X    }
  897. X
  898. X    nusers = atoi(argv[1]);
  899. X    if (nusers < 1) {
  900. X    fprintf(stderr, "%s: impossible nusers (%d<-%s)\n", prog, nusers, argv[1]);
  901. X    exit(4);
  902. X    }
  903. X    fprintf(stderr, "%d Users\n", nusers);
  904. X    argc--;
  905. X    argv++;
  906. X
  907. X    /* build job streams */
  908. X    getwork();
  909. X#if debug
  910. X    dumpwork();
  911. X#endif
  912. X
  913. X    /* clone copies of myself to run up to MAXCHILD jobs each */
  914. X    firstuser = MAXCHILD;
  915. X    fprintf(stderr, "master pid %d\n", getpid());
  916. X    fflush(stderr);
  917. X    while (nusers > MAXCHILD) {
  918. X    fflush(stderr);
  919. X    if (nusers >= 2*MAXCHILD)
  920. X        /* the next clone must run MAXCHILD jobs */
  921. X        nchild = MAXCHILD;
  922. X    else
  923. X        /* the next clone must run the leftover jobs */
  924. X        nchild = nusers - MAXCHILD;
  925. X    if ((l = fork()) == -1) {
  926. X        /* fork failed */
  927. X        fatal("** clone fork failed **\n");
  928. X        goto bepatient;
  929. X    } else if (l > 0) {
  930. X        fprintf(stderr, "master clone pid %d\n", l);
  931. X        /* I am the master with nchild fewer jobs to run */
  932. X        nusers -= nchild;
  933. X        firstuser += MAXCHILD;
  934. X        continue;
  935. X    } else {
  936. X        /* I am a clone, run MAXCHILD jobs */
  937. X#if ! debug
  938. X        sprintf(logname, "masterlog.%02d", firstuser/MAXCHILD);
  939. X        freopen(logname, "w", stderr);
  940. X#endif
  941. X        master = 0;
  942. X        nusers = nchild;
  943. X        break;
  944. X    }
  945. X    }
  946. X    if (master)
  947. X    firstuser = 0;
  948. X
  949. X    close(0);
  950. X    for (i = 0; i < nusers; i++ ) {
  951. X    fprintf(stderr, "user %d job %d ", firstuser+i, thiswork);
  952. X    if (pipe(pvec) == -1) {
  953. X        /* this is fatal */
  954. X        fatal("** pipe failed **\n");
  955. X        goto bepatient;
  956. X    }
  957. X    fflush(stderr);
  958. X    if ((child[i].pid = fork()) == 0) {
  959. X        int    fd;
  960. X        /* the command */
  961. X        if (pvec[0] != 0) {
  962. X        close(0);
  963. X        dup(pvec[0]);
  964. X        }
  965. X#if ! debug
  966. X        sprintf(logname, "userlog.%02d", firstuser+i);
  967. X        freopen(logname, "w", stderr);
  968. X#endif
  969. X        for (fd = 3; fd < 24; fd++)
  970. X        close(fd);
  971. X        if (work[thiswork].outf[0] != '\0') {
  972. X        /* redirect std output */
  973. X        char    *q;
  974. X        for (q = work[thiswork].outf; *q != '\n'; q++) ;
  975. X        *q = '\0';
  976. X        if (freopen(work[thiswork].outf, "w", stdout) == NULL) {
  977. X            fprintf(stderr, "makework: cannot open %s for std output\n",
  978. X            work[thiswork].outf);
  979. X            fflush(stderr);
  980. X        }
  981. X        *q = '\n';
  982. X        }
  983. X        execv(work[thiswork].cmd, work[thiswork].av);
  984. X        /* don't expect to get here! */
  985. X        fatal("** exec failed **\n");
  986. X        goto bepatient;
  987. X    }
  988. X    else if (child[i].pid == -1) {
  989. X        fatal("** fork failed **\n");
  990. X        goto bepatient;
  991. X    }
  992. X    else {
  993. X        close(pvec[0]);
  994. X        child[i].fd = pvec[1];
  995. X        child[i].line = child[i].bp = work[thiswork].input;
  996. X        child[i].blen = work[thiswork].inpsize;
  997. X        child[i].thisjob = thiswork;
  998. X        child[i].firstjob = thiswork;
  999. X        fprintf(stderr, "pid %d pipe fd %d", child[i].pid, child[i].fd);
  1000. X        if (work[thiswork].outf[0] != '\0') {
  1001. X        char *q;
  1002. X        fprintf(stderr, " > ");
  1003. X        for (q=work[thiswork].outf; *q != '\n'; q++)
  1004. X            fputc(*q, stderr);
  1005. X        }
  1006. X        fputc('\n', stderr);
  1007. X        thiswork++;
  1008. X        if (thiswork >= nwork)
  1009. X        thiswork = 0;
  1010. X    }
  1011. X    }
  1012. X    fflush(stderr);
  1013. X
  1014. X    srand(time(0));
  1015. X    thres = 0;
  1016. X    done = output = 0;
  1017. X    for (i = 0; i < nusers; i++) {
  1018. X    if (child[i].blen == 0)
  1019. X        done++;
  1020. X    else
  1021. X        thres += est_rate * GRANULE;
  1022. X    }
  1023. X    est_rate = thres;
  1024. X
  1025. X    signal(SIGALRM, onalarm);
  1026. X    signal(SIGPIPE, pipeerr);
  1027. X    alarm(GRANULE);
  1028. X    while (done < nusers) {
  1029. X    for (i = 0; i < nusers; i++) {
  1030. X        cp = &child[i];
  1031. X        if (cp->xmit >= cp->blen) continue;
  1032. X        l = rand() % CHUNK + 1;    /* 1-CHUNK chars */
  1033. X        if (l == 0) continue;
  1034. X        if (cp->xmit + l > cp->blen)
  1035. X        l = cp->blen - cp->xmit;
  1036. X        p = cp->bp;
  1037. X        cp->bp += l;
  1038. X        cp->xmit += l;
  1039. X#if debug
  1040. X        fprintf(stderr, "child %d, %d processed, %d to go\n", i, cp->xmit, cp->blen - cp->xmit);
  1041. X#endif
  1042. X        while (p < cp->bp) {
  1043. X        if (*p == '\n' || (p == &cp->bp[-1] && cp->xmit >= cp->blen)) {
  1044. X            /* write it out */
  1045. X            nch = p - cp->line + 1;
  1046. X            if ((written = write(cp->fd, cp->line, nch)) != nch) {
  1047. X            /* argh! */
  1048. X            cp->line[nch] = '\0';
  1049. X            fprintf(stderr, "user %d job %d cmd %s ",
  1050. X                firstuser+i, cp->thisjob, cp->line);
  1051. X             fprintf(stderr, "write(,,%d) returns %d\n", nch, written);
  1052. X            if (sigpipe)
  1053. X                fatal("** SIGPIPE error **\n");
  1054. X            else
  1055. X                fatal("** write error **\n");
  1056. X            goto bepatient;
  1057. X
  1058. X            }
  1059. X            if (fcopy)
  1060. X            write(fcopy, cp->line, p - cp->line + 1);
  1061. X#if debug
  1062. X            fprintf(stderr, "child %d gets \"", i);
  1063. X            {
  1064. X            char *q = cp->line;
  1065. X            while (q <= p) {
  1066. X                if (*q >= ' ' && *q <= '~')
  1067. X                    fputc(*q, stderr);
  1068. X                else
  1069. X                    fprintf(stderr, "\\%03o", *q);
  1070. X                q++;
  1071. X            }
  1072. X            }
  1073. X            fputc('"', stderr);
  1074. X#endif
  1075. X            cp->line = &p[1];
  1076. X        }
  1077. X        p++;
  1078. X        }
  1079. X        if (cp->xmit >= cp->blen) {
  1080. X        done++;
  1081. X        close(cp->fd);
  1082. X#if debug
  1083. X    fprintf(stderr, "child %d, close std input\n", i);
  1084. X#endif
  1085. X        }
  1086. X        output += l;
  1087. X    }
  1088. X    while (output > thres) {
  1089. X        pause();
  1090. X#if debug
  1091. X        fprintf(stderr, "after pause: output, thres, done %d %.2f %d\n", output, thres, done);
  1092. X#endif
  1093. X    }
  1094. X    }
  1095. X
  1096. bepatient:
  1097. X    alarm(0);
  1098. X/****
  1099. X *  If everything is going OK, we should simply be able to keep
  1100. X *  looping unitil 'wait' fails, however some descendent process may
  1101. X *  be in a state from which it can never exit, and so a timeout
  1102. X *  is used.
  1103. X *  5 minutes should be ample, since the time to run all jobs is of
  1104. X *  the order of 5-10 minutes, however some machines are painfully slow,
  1105. X *  so the timeout has been set at 20 minutes (1200 seconds).
  1106. X ****/
  1107. X    signal(SIGALRM, grunt);
  1108. X    alarm(1200);
  1109. X    while ((c = wait(&l)) != -1) {
  1110. X        for (i = 0; i < nusers; i++) {
  1111. X        if (c == child[i].pid) {
  1112. X        fprintf(stderr, "user %d job %d pid %d done", firstuser+i, child[i].thisjob, c);
  1113. X        if (l != 0) {
  1114. X            if (l & 0x7f)
  1115. X            fprintf(stderr, " status %d", l & 0x7f);
  1116. X            if (l & 0xff00)
  1117. X            fprintf(stderr, " exit code %d", (l>>8) & 0xff);
  1118. X            exit_status = 4;
  1119. X        }
  1120. X        fputc('\n', stderr);
  1121. X        c = child[i].pid = -1;
  1122. X        break;
  1123. X        }
  1124. X    }
  1125. X    if (c != -1) {
  1126. X        fprintf(stderr, "master clone done, pid %d ", c);
  1127. X        if (l != 0) {
  1128. X        if (l & 0x7f)
  1129. X            fprintf(stderr, " status %d", l & 0x7f);
  1130. X        if (l & 0xff00)
  1131. X            fprintf(stderr, " exit code %d", (l>>8) & 0xff);
  1132. X        exit_status = 4;
  1133. X        }
  1134. X        fputc('\n', stderr);
  1135. X    }
  1136. X    }
  1137. X    alarm(0);
  1138. X    wrapup("Finished waiting ...");
  1139. X
  1140. X
  1141. X}
  1142. X
  1143. onalarm()
  1144. X{
  1145. X    thres += est_rate;
  1146. X    signal(SIGALRM, onalarm);
  1147. X    alarm(GRANULE);
  1148. X}
  1149. X
  1150. grunt()
  1151. X{
  1152. X    /* timeout after label "bepatient" in main */
  1153. X    exit_status = 4;
  1154. X    wrapup("Timed out waiting for jobs to finish ...");
  1155. X}
  1156. X
  1157. pipeerr()
  1158. X{
  1159. X    sigpipe++;
  1160. X}
  1161. X
  1162. wrapup(reason)
  1163. char    *reason;
  1164. X{
  1165. X    int i;
  1166. X    int killed = 0;
  1167. X    fflush(stderr);
  1168. X    for (i = 0; i < nusers; i++) {
  1169. X    if (child[i].pid > 0 && kill(child[i].pid, SIGKILL) != -1) {
  1170. X        if (!killed) {
  1171. X        killed++;
  1172. X        fprintf(stderr, "%s\n", reason);
  1173. X        fflush(stderr);
  1174. X        }
  1175. X        fprintf(stderr, "user %d job %d pid %d killed off\n", firstuser+i, child[i].thisjob, child[i].pid);
  1176. X    fflush(stderr);
  1177. X    }
  1178. X    }
  1179. X    exit(exit_status);
  1180. X}
  1181. X
  1182. getwork()
  1183. X{
  1184. X    int            i;
  1185. X    int            f;
  1186. X    int            ac;
  1187. X    char        *lp;
  1188. X    char        *q;
  1189. X    struct st_work    *w;
  1190. X    char        line[512];
  1191. X    char        c;
  1192. X    char        *malloc(), *realloc();
  1193. X
  1194. X    while (gets(line) != NULL) {
  1195. X    if (nwork >= MAXWORK) {
  1196. X        fprintf(stderr, stderr, "Too many jobs specified, .. increase MAXWORK\n");
  1197. X        exit(4);
  1198. X    }
  1199. X    w = &work[nwork];
  1200. X    lp = line;
  1201. X    i = 1;
  1202. X    while (*lp && *lp != ' ') {
  1203. X        i++;
  1204. X        lp++;
  1205. X    }
  1206. X    w->cmd = (char *)malloc(i);
  1207. X    strncpy(w->cmd, line, i-1);
  1208. X    w->cmd[i-1] = '\0';
  1209. X    w->inpsize = 0;
  1210. X    w->input = "";
  1211. X    /* start to build arg list */
  1212. X    ac = 2;
  1213. X    w->av = (char **)malloc(2*sizeof(char *));
  1214. X    q = w->cmd;
  1215. X    while (*q) q++;
  1216. X    q--;
  1217. X    while (q >= w->cmd) {
  1218. X        if (*q == '/') {
  1219. X        q++;
  1220. X        break;
  1221. X        }
  1222. X        q--;
  1223. X    }
  1224. X    w->av[0] = q;
  1225. X    while (*lp) {
  1226. X        if (*lp == ' ') {
  1227. X        /* space */
  1228. X        lp++;
  1229. X        continue;
  1230. X        }
  1231. X        else if (*lp == '<') {
  1232. X        /* standard input for this job */
  1233. X        q = ++lp;
  1234. X        while (*lp && *lp != ' ') lp++;
  1235. X        c = *lp;
  1236. X        *lp = '\0';
  1237. X        if ((f = open(q, 0)) == -1) {
  1238. X            fprintf(stderr, "cannot open input file (%s) for job %d\n",
  1239. X                q, nwork);
  1240. X            exit(4);
  1241. X        }
  1242. X        /* gobble input */
  1243. X        w->input = (char *)malloc(512);
  1244. X        while ((i = read(f, &w->input[w->inpsize], 512)) > 0) {
  1245. X            w->inpsize += i;
  1246. X            w->input = (char *)realloc(w->input, w->inpsize+512);
  1247. X        }
  1248. X        w->input = (char *)realloc(w->input, w->inpsize);
  1249. X        close(f);
  1250. X        /* extract stdout file name from line beginning "C=" */
  1251. X        w->outf = "";
  1252. X        for (q = w->input; q < &w->input[w->inpsize-10]; q++) {
  1253. X            if (*q == '\n' && strncmp(&q[1], "C=", 2) == 0) {
  1254. X            w->outf = &q[3];
  1255. X            break;
  1256. X            }
  1257. X        }
  1258. X#if debug
  1259. X        if (*w->outf) {
  1260. X            fprintf(stderr, "stdout->");
  1261. X            for (q=w->outf; *q != '\n'; q++)
  1262. X            fputc(*q, stderr);
  1263. X            fputc('\n', stderr);
  1264. X        }
  1265. X#endif
  1266. X        }
  1267. X        else {
  1268. X        /* a command option */
  1269. X        ac++;
  1270. X        w->av = (char **)realloc(w->av, ac*sizeof(char *));
  1271. X        q = lp;
  1272. X        i = 1;
  1273. X        while (*lp && *lp != ' ') {
  1274. X            lp++;
  1275. X            i++;
  1276. X        }
  1277. X        w->av[ac-2] = (char *)malloc(i);
  1278. X        strncpy(w->av[ac-2], q, i-1);
  1279. X        w->av[ac-2][i-1] = '\0';
  1280. X        }
  1281. X    }
  1282. X    w->av[ac-1] = (char *)0;
  1283. X    nwork++;
  1284. X    }
  1285. X}
  1286. X
  1287. X#if debug
  1288. dumpwork()
  1289. X{
  1290. X    int        i;
  1291. X    int        j;
  1292. X
  1293. X    for (i = 0; i < nwork; i++) {
  1294. X    fprintf(stderr, "job %d: cmd: %s\n", i, work[i].cmd);
  1295. X    j = 0;
  1296. X    while (work[i].av[j]) {
  1297. X        fprintf(stderr, "argv[%d]: %s\n", j, work[i].av[j]);
  1298. X        j++;
  1299. X    }
  1300. X    fprintf(stderr, "input: %d chars text: ", work[i].inpsize);
  1301. X    if (work[i].input == (char *)0)
  1302. X        fprintf(stderr, "<NULL>\n");
  1303. X    else {
  1304. X            register char    *pend;
  1305. X            char        *p;
  1306. X        char        c;
  1307. X        p = work[i].input;
  1308. X        while (*p) {
  1309. X            pend = p;
  1310. X            while (*pend && *pend != '\n')
  1311. X                pend++;
  1312. X            c = *pend;
  1313. X            *pend = '\0';
  1314. X            fprintf(stderr, "%s\n", p);
  1315. X            *pend = c;
  1316. X            p = &pend[1];
  1317. X        }
  1318. X    }
  1319. X    }
  1320. X}
  1321. X#endif
  1322. X
  1323. fatal(s)
  1324. char *s;
  1325. X{
  1326. X    int    i;
  1327. X    fprintf(stderr, s);
  1328. X    fflush(stderr);
  1329. X    perror("Reason?");
  1330. X    fflush(stderr);
  1331. X    for (i = 0; i < nusers; i++) {
  1332. X    if (child[i].pid > 0 && kill(child[i].pid, SIGKILL) != -1) {
  1333. X        fprintf(stderr, "pid %d killed off\n", child[i].pid);
  1334. X        fflush(stderr);
  1335. X    }
  1336. X    }
  1337. X    exit_status = 4;
  1338. X    return;
  1339. X}
  1340. END_OF_FILE
  1341. if test 13785 -ne `wc -c <'src/big.c'`; then
  1342.     echo shar: \"'src/big.c'\" unpacked with wrong size!
  1343. fi
  1344. chmod +x 'src/big.c'
  1345. # end of 'src/big.c'
  1346. fi
  1347. if test -f 'src/dhry_1.c' -a "${1}" != "-c" ; then 
  1348.   echo shar: Will not clobber existing file \"'src/dhry_1.c'\"
  1349. else
  1350. echo shar: Extracting \"'src/dhry_1.c'\" \(12970 characters\)
  1351. sed "s/^X//" >'src/dhry_1.c' <<'END_OF_FILE'
  1352. X/*****************************************************************************
  1353. X *  The BYTE UNIX Benchmarks - Release 3
  1354. X *          Module: dhry_1.c   SID: 3.4 5/15/91 19:30:21
  1355. X *          
  1356. X *****************************************************************************
  1357. X * Bug reports, patches, comments, suggestions should be sent to:
  1358. X *
  1359. X *    Ben Smith, Rick Grehan or Tom Yager
  1360. X *    ben@bytepb.byte.com   rick_g@bytepb.byte.com   tyager@bytepb.byte.com
  1361. X *
  1362. X *****************************************************************************
  1363. X *
  1364. X * *** WARNING ****  With BYTE's modifications applied, results obtained with
  1365. X *     *******       this version of the Dhrystone program may not be applicable
  1366. X *                   to other versions.
  1367. X *                  
  1368. X *  Modification Log:
  1369. X *
  1370. X *  Adapted from:
  1371. X *
  1372. X *                   "DHRYSTONE" Benchmark Program
  1373. X *                   -----------------------------
  1374. X *                                                                            
  1375. X *  Version:    C, Version 2.1
  1376. X *                                                                            
  1377. X *  File:       dhry_1.c (part 2 of 3)
  1378. X *
  1379. X *  Date:       May 25, 1988
  1380. X *
  1381. X *  Author:     Reinhold P. Weicker
  1382. X *
  1383. X ***************************************************************************/
  1384. char SCCSid[] = "@(#) @(#)dhry_1.c:3.4 -- 5/15/91 19:30:21";
  1385. X
  1386. X#include <stdio.h>
  1387. X#include "dhry.h"
  1388. X#include "timeit.c"
  1389. X
  1390. unsigned long Run_Index;
  1391. X
  1392. report()
  1393. X{
  1394. X    fprintf(stderr,"%ld loops\n", Run_Index);
  1395. X    exit(0);
  1396. X}
  1397. X
  1398. X/* Global Variables: */
  1399. X
  1400. Rec_Pointer     Ptr_Glob,
  1401. X                Next_Ptr_Glob;
  1402. int             Int_Glob;
  1403. Boolean         Bool_Glob;
  1404. char            Ch_1_Glob,
  1405. X                Ch_2_Glob;
  1406. int             Arr_1_Glob [50];
  1407. int             Arr_2_Glob [50] [50];
  1408. X
  1409. extern char     *malloc ();
  1410. XEnumeration     Func_1 ();
  1411. X  /* forward declaration necessary since Enumeration may not simply be int */
  1412. X
  1413. X#ifndef REG
  1414. X        Boolean Reg = false;
  1415. X#define REG
  1416. X        /* REG becomes defined as empty */
  1417. X        /* i.e. no register variables   */
  1418. X#else
  1419. X        Boolean Reg = true;
  1420. X#endif
  1421. X
  1422. X/* variables for time measurement: */
  1423. X
  1424. X#ifdef TIMES
  1425. struct tms      time_info;
  1426. extern  int     times ();
  1427. X                /* see library function "times" */
  1428. X#define Too_Small_Time 120
  1429. X                /* Measurements should last at least about 2 seconds */
  1430. X#endif
  1431. X#ifdef TIME
  1432. extern long     time();
  1433. X                /* see library function "time"  */
  1434. X#define Too_Small_Time 2
  1435. X                /* Measurements should last at least 2 seconds */
  1436. X#endif
  1437. X
  1438. long            Begin_Time,
  1439. X                End_Time,
  1440. X                User_Time;
  1441. float           Microseconds,
  1442. X                Dhrystones_Per_Second;
  1443. X
  1444. X/* end of variables for time measurement */
  1445. X
  1446. X
  1447. main (argc, argv, env)
  1448. int argc;
  1449. char *argv[], *env[];
  1450. X/*****/
  1451. X
  1452. X  /* main program, corresponds to procedures        */
  1453. X  /* Main and Proc_0 in the Ada version             */
  1454. X{
  1455. X        int             duration;
  1456. X        One_Fifty       Int_1_Loc;
  1457. X  REG   One_Fifty       Int_2_Loc;
  1458. X        One_Fifty       Int_3_Loc;
  1459. X  REG   char            Ch_Index;
  1460. X        Enumeration     Enum_Loc;
  1461. X        Str_30          Str_1_Loc;
  1462. X        Str_30          Str_2_Loc;
  1463. X  REG   int             Number_Of_Runs;
  1464. X
  1465. X  /* Initializations */
  1466. X
  1467. X  Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
  1468. X  Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
  1469. X
  1470. X  Ptr_Glob->Ptr_Comp                    = Next_Ptr_Glob;
  1471. X  Ptr_Glob->Discr                       = Ident_1;
  1472. X  Ptr_Glob->variant.var_1.Enum_Comp     = Ident_3;
  1473. X  Ptr_Glob->variant.var_1.Int_Comp      = 40;
  1474. X  strcpy (Ptr_Glob->variant.var_1.Str_Comp, 
  1475. X          "DHRYSTONE PROGRAM, SOME STRING");
  1476. X  strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
  1477. X
  1478. X  Arr_2_Glob [8][7] = 10;
  1479. X        /* Was missing in published program. Without this statement,    */
  1480. X        /* Arr_2_Glob [8][7] would have an undefined value.             */
  1481. X        /* Warning: With 16-Bit processors and Number_Of_Runs > 32000,  */
  1482. X        /* overflow may occur for this array element.                   */
  1483. X
  1484. X#ifdef PRATTLE
  1485. X  printf ("\n");
  1486. X  printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
  1487. X  printf ("\n");
  1488. X  if (Reg)
  1489. X  {
  1490. X    printf ("Program compiled with 'register' attribute\n");
  1491. X    printf ("\n");
  1492. X  }
  1493. X  else
  1494. X  {
  1495. X    printf ("Program compiled without 'register' attribute\n");
  1496. X    printf ("\n");
  1497. X  }
  1498. X  printf ("Please give the number of runs through the benchmark: ");
  1499. X  {
  1500. X    int n;
  1501. X    scanf ("%d", &n);
  1502. X    Number_Of_Runs = n;
  1503. X  }
  1504. X  printf ("\n");
  1505. X
  1506. X  printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs);
  1507. X#endif /* PRATTLE */
  1508. X
  1509. X  if (argc != 2) {
  1510. X    printf("Usage: %s duration\n", argv[0]);
  1511. X    exit(1);
  1512. X    }
  1513. X
  1514. X  duration = atoi(argv[1]);
  1515. X  Run_Index = 0;
  1516. X  wake_me(duration, report);
  1517. X
  1518. X  /***************/
  1519. X  /* Start timer */
  1520. X  /***************/
  1521. X#ifdef SELF_TIMED
  1522. X#ifdef TIMES
  1523. X  times (&time_info);
  1524. X  Begin_Time = (long) time_info.tms_utime;
  1525. X#endif
  1526. X#ifdef TIME
  1527. X  Begin_Time = time ( (long *) 0);
  1528. X#endif
  1529. X#endif /* SELF_TIMED */
  1530. X
  1531. X  for (Run_Index = 1; ; ++Run_Index)
  1532. X  {
  1533. X
  1534. X    Proc_5();
  1535. X    Proc_4();
  1536. X      /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
  1537. X    Int_1_Loc = 2;
  1538. X    Int_2_Loc = 3;
  1539. X    strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
  1540. X    Enum_Loc = Ident_2;
  1541. X    Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
  1542. X      /* Bool_Glob == 1 */
  1543. X    while (Int_1_Loc < Int_2_Loc)  /* loop body executed once */
  1544. X    {
  1545. X      Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
  1546. X        /* Int_3_Loc == 7 */
  1547. X      Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
  1548. X        /* Int_3_Loc == 7 */
  1549. X      Int_1_Loc += 1;
  1550. X    } /* while */
  1551. X      /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
  1552. X    Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
  1553. X      /* Int_Glob == 5 */
  1554. X    Proc_1 (Ptr_Glob);
  1555. X    for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
  1556. X                             /* loop body executed twice */
  1557. X    {
  1558. X      if (Enum_Loc == Func_1 (Ch_Index, 'C'))
  1559. X          /* then, not executed */
  1560. X        {
  1561. X        Proc_6 (Ident_1, &Enum_Loc);
  1562. X        strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
  1563. X        Int_2_Loc = Run_Index;
  1564. X        Int_Glob = Run_Index;
  1565. X        }
  1566. X    }
  1567. X      /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
  1568. X    Int_2_Loc = Int_2_Loc * Int_1_Loc;
  1569. X    Int_1_Loc = Int_2_Loc / Int_3_Loc;
  1570. X    Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
  1571. X      /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
  1572. X    Proc_2 (&Int_1_Loc);
  1573. X      /* Int_1_Loc == 5 */
  1574. X
  1575. X  } /* loop "for Run_Index" */
  1576. X
  1577. X  /**************/
  1578. X  /* Stop timer */
  1579. X  /**************/
  1580. X#ifdef SELF_TIMED 
  1581. X#ifdef TIMES
  1582. X  times (&time_info);
  1583. X  End_Time = (long) time_info.tms_utime;
  1584. X#endif
  1585. X#ifdef TIME
  1586. X  End_Time = time ( (long *) 0);
  1587. X#endif
  1588. X#endif /* SELF_TIMED */
  1589. X
  1590. X  /* BYTE version never executes this stuff */
  1591. X#ifdef SELF_TIMED
  1592. X  printf ("Execution ends\n");
  1593. X  printf ("\n");
  1594. X  printf ("Final values of the variables used in the benchmark:\n");
  1595. X  printf ("\n");
  1596. X  printf ("Int_Glob:            %d\n", Int_Glob);
  1597. X  printf ("        should be:   %d\n", 5);
  1598. X  printf ("Bool_Glob:           %d\n", Bool_Glob);
  1599. X  printf ("        should be:   %d\n", 1);
  1600. X  printf ("Ch_1_Glob:           %c\n", Ch_1_Glob);
  1601. X  printf ("        should be:   %c\n", 'A');
  1602. X  printf ("Ch_2_Glob:           %c\n", Ch_2_Glob);
  1603. X  printf ("        should be:   %c\n", 'B');
  1604. X  printf ("Arr_1_Glob[8]:       %d\n", Arr_1_Glob[8]);
  1605. X  printf ("        should be:   %d\n", 7);
  1606. X  printf ("Arr_2_Glob[8][7]:    %d\n", Arr_2_Glob[8][7]);
  1607. X  printf ("        should be:   Number_Of_Runs + 10\n");
  1608. X  printf ("Ptr_Glob->\n");
  1609. X  printf ("  Ptr_Comp:          %d\n", (int) Ptr_Glob->Ptr_Comp);
  1610. X  printf ("        should be:   (implementation-dependent)\n");
  1611. X  printf ("  Discr:             %d\n", Ptr_Glob->Discr);
  1612. X  printf ("        should be:   %d\n", 0);
  1613. X  printf ("  Enum_Comp:         %d\n", Ptr_Glob->variant.var_1.Enum_Comp);
  1614. X  printf ("        should be:   %d\n", 2);
  1615. X  printf ("  Int_Comp:          %d\n", Ptr_Glob->variant.var_1.Int_Comp);
  1616. X  printf ("        should be:   %d\n", 17);
  1617. X  printf ("  Str_Comp:          %s\n", Ptr_Glob->variant.var_1.Str_Comp);
  1618. X  printf ("        should be:   DHRYSTONE PROGRAM, SOME STRING\n");
  1619. X  printf ("Next_Ptr_Glob->\n");
  1620. X  printf ("  Ptr_Comp:          %d\n", (int) Next_Ptr_Glob->Ptr_Comp);
  1621. X  printf ("        should be:   (implementation-dependent), same as above\n");
  1622. X  printf ("  Discr:             %d\n", Next_Ptr_Glob->Discr);
  1623. X  printf ("        should be:   %d\n", 0);
  1624. X  printf ("  Enum_Comp:         %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp);
  1625. X  printf ("        should be:   %d\n", 1);
  1626. X  printf ("  Int_Comp:          %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp);
  1627. X  printf ("        should be:   %d\n", 18);
  1628. X  printf ("  Str_Comp:          %s\n",
  1629. X                                Next_Ptr_Glob->variant.var_1.Str_Comp);
  1630. X  printf ("        should be:   DHRYSTONE PROGRAM, SOME STRING\n");
  1631. X  printf ("Int_1_Loc:           %d\n", Int_1_Loc);
  1632. X  printf ("        should be:   %d\n", 5);
  1633. X  printf ("Int_2_Loc:           %d\n", Int_2_Loc);
  1634. X  printf ("        should be:   %d\n", 13);
  1635. X  printf ("Int_3_Loc:           %d\n", Int_3_Loc);
  1636. X  printf ("        should be:   %d\n", 7);
  1637. X  printf ("Enum_Loc:            %d\n", Enum_Loc);
  1638. X  printf ("        should be:   %d\n", 1);
  1639. X  printf ("Str_1_Loc:           %s\n", Str_1_Loc);
  1640. X  printf ("        should be:   DHRYSTONE PROGRAM, 1'ST STRING\n");
  1641. X  printf ("Str_2_Loc:           %s\n", Str_2_Loc);
  1642. X  printf ("        should be:   DHRYSTONE PROGRAM, 2'ND STRING\n");
  1643. X  printf ("\n");
  1644. X
  1645. X  User_Time = End_Time - Begin_Time;
  1646. X
  1647. X  if (User_Time < Too_Small_Time)
  1648. X  {
  1649. X    printf ("Measured time too small to obtain meaningful results\n");
  1650. X    printf ("Please increase number of runs\n");
  1651. X    printf ("\n");
  1652. X  }
  1653. X  else
  1654. X  {
  1655. X#ifdef TIME
  1656. X    Microseconds = (float) User_Time * Mic_secs_Per_Second 
  1657. X                        / (float) Number_Of_Runs;
  1658. X    Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time;
  1659. X#else
  1660. X    Microseconds = (float) User_Time * Mic_secs_Per_Second 
  1661. X                        / ((float) HZ * ((float) Number_Of_Runs));
  1662. X    Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs)
  1663. X                        / (float) User_Time;
  1664. X#endif
  1665. X    printf ("Microseconds for one run through Dhrystone: ");
  1666. X    printf ("%6.1f \n", Microseconds);
  1667. X    printf ("Dhrystones per Second:                      ");
  1668. X    printf ("%6.1f \n", Dhrystones_Per_Second);
  1669. X    printf ("\n");
  1670. X  }
  1671. X#endif /* SELF_TIMED */
  1672. X}
  1673. X
  1674. X
  1675. Proc_1 (Ptr_Val_Par)
  1676. X/******************/
  1677. X
  1678. REG Rec_Pointer Ptr_Val_Par;
  1679. X    /* executed once */
  1680. X{
  1681. X  REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;  
  1682. X                                        /* == Ptr_Glob_Next */
  1683. X  /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp,    */
  1684. X  /* corresponds to "rename" in Ada, "with" in Pascal           */
  1685. X  
  1686. X  structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob); 
  1687. X  Ptr_Val_Par->variant.var_1.Int_Comp = 5;
  1688. X  Next_Record->variant.var_1.Int_Comp 
  1689. X        = Ptr_Val_Par->variant.var_1.Int_Comp;
  1690. X  Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
  1691. X  Proc_3 (&Next_Record->Ptr_Comp);
  1692. X    /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp 
  1693. X                        == Ptr_Glob->Ptr_Comp */
  1694. X  if (Next_Record->Discr == Ident_1)
  1695. X    /* then, executed */
  1696. X  {
  1697. X    Next_Record->variant.var_1.Int_Comp = 6;
  1698. X    Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp, 
  1699. X           &Next_Record->variant.var_1.Enum_Comp);
  1700. X    Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
  1701. X    Proc_7 (Next_Record->variant.var_1.Int_Comp, 10, 
  1702. X           &Next_Record->variant.var_1.Int_Comp);
  1703. X  }
  1704. X  else /* not executed */
  1705. X    structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
  1706. X} /* Proc_1 */
  1707. X
  1708. X
  1709. Proc_2 (Int_Par_Ref)
  1710. X/******************/
  1711. X    /* executed once */
  1712. X    /* *Int_Par_Ref == 1, becomes 4 */
  1713. X
  1714. One_Fifty   *Int_Par_Ref;
  1715. X{
  1716. X  One_Fifty  Int_Loc;  
  1717. X  Enumeration   Enum_Loc;
  1718. X
  1719. X  Int_Loc = *Int_Par_Ref + 10;
  1720. X  do /* executed once */
  1721. X    if (Ch_1_Glob == 'A')
  1722. X      /* then, executed */
  1723. X    {
  1724. X      Int_Loc -= 1;
  1725. X      *Int_Par_Ref = Int_Loc - Int_Glob;
  1726. X      Enum_Loc = Ident_1;
  1727. X    } /* if */
  1728. X  while (Enum_Loc != Ident_1); /* true */
  1729. X} /* Proc_2 */
  1730. X
  1731. X
  1732. Proc_3 (Ptr_Ref_Par)
  1733. X/******************/
  1734. X    /* executed once */
  1735. X    /* Ptr_Ref_Par becomes Ptr_Glob */
  1736. X
  1737. Rec_Pointer *Ptr_Ref_Par;
  1738. X
  1739. X{
  1740. X  if (Ptr_Glob != Null)
  1741. X    /* then, executed */
  1742. X    *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
  1743. X  Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
  1744. X} /* Proc_3 */
  1745. X
  1746. X
  1747. Proc_4 () /* without parameters */
  1748. X/*******/
  1749. X    /* executed once */
  1750. X{
  1751. X  Boolean Bool_Loc;
  1752. X
  1753. X  Bool_Loc = Ch_1_Glob == 'A';
  1754. X  Bool_Glob = Bool_Loc | Bool_Glob;
  1755. X  Ch_2_Glob = 'B';
  1756. X} /* Proc_4 */
  1757. X
  1758. X
  1759. Proc_5 () /* without parameters */
  1760. X/*******/
  1761. X    /* executed once */
  1762. X{
  1763. X  Ch_1_Glob = 'A';
  1764. X  Bool_Glob = false;
  1765. X} /* Proc_5 */
  1766. X
  1767. X
  1768. X        /* Procedure for the assignment of structures,          */
  1769. X        /* if the C compiler doesn't support this feature       */
  1770. X#ifdef  NOSTRUCTASSIGN
  1771. memcpy (d, s, l)
  1772. register char   *d;
  1773. register char   *s;
  1774. register int    l;
  1775. X{
  1776. X        while (l--) *d++ = *s++;
  1777. X}
  1778. X#endif
  1779. X
  1780. X
  1781. END_OF_FILE
  1782. if test 12970 -ne `wc -c <'src/dhry_1.c'`; then
  1783.     echo shar: \"'src/dhry_1.c'\" unpacked with wrong size!
  1784. fi
  1785. chmod +x 'src/dhry_1.c'
  1786. # end of 'src/dhry_1.c'
  1787. fi
  1788. echo shar: End of archive 3 \(of 4\).
  1789. cp /dev/null ark3isdone
  1790. MISSING=""
  1791. for I in 1 2 3 4 ; do
  1792.     if test ! -f ark${I}isdone ; then
  1793.     MISSING="${MISSING} ${I}"
  1794.     fi
  1795. done
  1796. if test "${MISSING}" = "" ; then
  1797.     echo You have unpacked all 4 archives.
  1798.     rm -f ark[1-9]isdone
  1799. else
  1800.     echo You still need to unpack the following archives:
  1801.     echo "        " ${MISSING}
  1802. fi
  1803. ##  End of shell archive.
  1804. exit 0
  1805.