From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 23-JUN-1990 02:30:18.06
To:	MRGATE::"ARISIA::EVERHART"
CC:	
Subj:	MSCP caching and served disks -- is it working?

Received:  by crdgw1.ge.com (5.57/GE 1.70)
	 id AA00353; Fri, 22 Jun 90 22:54:23 EDT
Received: From SLCS.SLB.COM by CRVAX.SRI.COM with TCP; Fri, 22 JUN 90 11:13:46 PDT
Received: from prsrtr.psi
	by SLCS.SLB.COM (4.1/SLCS Mailhost 3.2)
	id AA21225; Fri, 22 Jun 90 13:13:53 CDT
Date: Fri, 22 Jun 90 13:13:53 CDT
From: weissborn%jas@hub.SINet.SLB.COM (Bill Weissborn, DSR-Staff Eng.  214 980-7924)
Message-Id: <9006221813.AA21225.weissborn%jas@hub.SINet.SLB.COM@SLCS.SLB.COM>
To: info-vax@sri.com
X-Vms-To: HUB::M_MAILNOW::M_INTERNET::"info-vax@sri.com"
Subject: MSCP caching and served disks -- is it working?

DEC has consistently claimed, at various levels, that MSCP caching should
provide superior I/O performance for diskless workstations AND/OR served-disks.

I wanted to investigate/substantiate this claim by DEC that MSCP caching would
give better disk I/O performance on served disks than would be available if
they were local to the workstation.  So I used the VDBM program that was talked
about in the December, 1989(I think) issue of DEC Professional.  

Based on my observations, exactly the opposite seems to be true, ie., I/O
throughput is extremely poor for a served-disk. And, "real-world/work"
performance seems to support the POOR performance shown in the test.  When we
talked with the local DEC guru, he did not have any idea why the I/O
performance was so bad.

I am very interested in this as our applications tend to be very I/O bound and
if MSCP caching (or the apparent lack thereof) is not working then it would be
more cost-effective for us to buy some of the newer disks to attach to the
3100s we are acquiring.

If anyone can explain what is going on I would appreciate it.  I have enclosed
both the original and modified version of VDBM.

Bill Weissborn
Schlumberger Well Services
12770 Coit Rd.  Suite 200
Dallas,  Tx.  75251
(214) 980-7924

weissborn%ntchcs@hub.sinet.slb.com   <==This should work

*****************************************************************************

TEST CONDITIONS:
----------------
NTCVX1: 11/780, 8MB, BOOT SERVER FOR 4 3100s
NTCVX3: 3100 BOOTED VIA NTCVX1, 8MB, 2 DISKS LOCAL


DSKA: LOCAL TO NTCVX1, RA81 CONNECTED VIA UDA-50
DSKB: LOCAL TO NTCVX1, RA81 CONNECTED VIA UDA-50
DSKC: LOCAL TO NTCVX1, EMULEX/UDA-50
DSKE: LOCAL TO NTCVX1, EMULEX/UDA-50 BOUND VOLUME(2 DISKS)
DSKJ: LOCAL TO NTCVX3, RZ55


Program was run 4 times on each disk.

ALL MACHINES CAN BE CONSIDERED IDLE, IE., NO OTHER USERS ON THE SYSTEM AT THE
TIME OF THE TEST, DECNET TRAFFIC NON-EXISTENT, ETC.


                                    NTCVX1

VAX Disk BenchMark V1.0-1
Working on...............: DSKA:                                   
Average Access Time is   :    42.96875     msec
Average Transfer Rate is :    175.9184     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.171641    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKA:                                   
Average Access Time is   :    42.96875     msec
Average Transfer Rate is :    188.0444     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.405969    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKA:                                   
Average Access Time is   :    42.96875     msec
Average Transfer Rate is :    181.5682     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.171641    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKA:                                   
Average Access Time is   :    39.06250     msec
Average Transfer Rate is :    191.3478     KB/Sec
Average Controller/Vms Overhead is:    6.210392     msec

==============================================================================
VAX Disk BenchMark V1.0-1
Working on...............: DSKB:                                   
Average Access Time is   :    35.15625     msec
Average Transfer Rate is :    331.2000     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.405969    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKB:                                   
Average Access Time is   :    39.06250     msec
Average Transfer Rate is :    379.5000     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.171641    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKB:                                   
Average Access Time is   :    31.25000     msec
Average Transfer Rate is :    420.6842     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.405969    disk revolutions.                    

VAX Disk BenchMark V1.0-1
Working on...............: DSKB:                                   
Average Access Time is   :    31.25000     msec
Average Transfer Rate is :    409.0000     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.171641    disk revolutions.

===============================================================================
VAX Disk BenchMark V1.0-1
Working on...............: DSKC:                                   
Average Access Time is   :    46.87500     msec
Average Transfer Rate is :    410.6000     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.171641    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKC:                                   
Average Access Time is   :    39.06250     msec
Average Transfer Rate is :    363.4546     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.171641    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKC:                                   
Average Access Time is   :    35.15625     msec
Average Transfer Rate is :    402.7500     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.171641    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKC:                                   
Average Access Time is   :    35.15625     msec
Average Transfer Rate is :    426.5789     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.171641    disk revolutions.

==============================================================================
VAX Disk BenchMark V1.0-1
Working on...............: DSKE:                                   
Average Access Time is   :    35.15625     msec
Average Transfer Rate is :    417.2500     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.405969    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKE:                                   
Average Access Time is   :    35.15625     msec
Average Transfer Rate is :    423.5000     KB/Sec
VMS controller overhead cannot be computed.

VAX Disk BenchMark V1.0-1
Working on...............: DSKE:                                   
Average Access Time is   :    35.15625     msec
Average Transfer Rate is :    441.3333     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.171641    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKE:                                   
Average Access Time is   :    35.15625     msec
Average Transfer Rate is :    419.5263     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.171641    disk revolutions.

===============================================================================
VAX Disk BenchMark V1.0-1
Working on...............: DSKJ:                                   
Average Access Time is   :    54.68750     msec
Average Transfer Rate is :    146.5965     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.405969    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKJ:                                   
Average Access Time is   :    50.78125     msec
Average Transfer Rate is :    147.3051     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.640297    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKJ:                                   
Average Access Time is   :    50.78125     msec
Average Transfer Rate is :    154.1053     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.405969    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKJ:                                   
Average Access Time is   :    50.78125     msec
Average Transfer Rate is :    143.5536     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.640297    disk revolutions.




                                    NTCVX3

VAX Disk BenchMark V1.0-1
Working on...............: DSKA:                                   
Average Access Time is   :    54.68750     msec
Average Transfer Rate is :    76.92437     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.405969    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKA:                                   
Average Access Time is   :    54.68750     msec
Average Transfer Rate is :    74.74775     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.640297    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKA:                                   
Average Access Time is   :    54.68750     msec
Average Transfer Rate is :    74.02542     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.874625    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKA:                                   
Average Access Time is   :    54.68750     msec
Average Transfer Rate is :    73.72072     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.874625    disk revolutions.

===============================================================================

VAX Disk BenchMark V1.0-1
Working on...............: DSKB:                                   
Average Access Time is   :    46.87500     msec
Average Transfer Rate is :    95.97591     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.874625    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKB:                                   
Average Access Time is   :    50.78125     msec
Average Transfer Rate is :    79.30000     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   2.343281    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKB:                                   
Average Access Time is   :    50.78125     msec
Average Transfer Rate is :    93.68965     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.874625    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKB:                                   
Average Access Time is   :    50.78125     msec
Average Transfer Rate is :    92.84884     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.874625    disk revolutions.

===============================================================================

VAX Disk BenchMark V1.0-1
Working on...............: DSKC:                                   
Average Access Time is   :    46.87500     msec
Average Transfer Rate is :    95.68674     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.874625    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKC:                                   
Average Access Time is   :    58.59375     msec
Average Transfer Rate is :    89.10588     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   2.108953    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKC:                                   
Average Access Time is   :    50.78125     msec
Average Transfer Rate is :    92.92941     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   3.280594    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKC:                                   
Average Access Time is   :    50.78125     msec
Average Transfer Rate is :    92.26744     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.874625    disk revolutions.

==============================================================================

VAX Disk BenchMark V1.0-1
Working on...............: DSKE:                                   
Average Access Time is   :    46.87500     msec
Average Transfer Rate is :    96.93903     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.874625    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKE:                                   
Average Access Time is   :    54.68750     msec
Average Transfer Rate is :    86.65934     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.874625    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKE:                                   
Average Access Time is   :    50.78125     msec
Average Transfer Rate is :    91.04651     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.874625    disk revolutions.

VAX Disk BenchMark V1.0-1
Working on...............: DSKE:                                   
Average Access Time is   :    46.87500     msec
Average Transfer Rate is :    94.87778     KB/Sec
VMS controller overhead cannot be computed.
The last access was made in   1.874625    disk revolutions.

==============================================================================

VAX Disk BenchMark V1.0-1
Working on...............: DSKJ:                                   
Average Access Time is   :    39.06250     msec
Average Transfer Rate is :    286.1482     KB/Sec
Average Controller/Vms Overhead is:    6.566970     msec

VAX Disk BenchMark V1.0-1
Working on...............: DSKJ:                                   
Average Access Time is   :    35.15625     msec
Average Transfer Rate is :    299.0000     KB/Sec
VMS controller overhead cannot be computed.

VAX Disk BenchMark V1.0-1
Working on...............: DSKJ:                                   
Average Access Time is   :    39.06250     msec
Average Transfer Rate is :    302.5357     KB/Sec
Average Controller/Vms Overhead is:    6.566970     msec

VAX Disk BenchMark V1.0-1
Working on...............: DSKJ:                                   
Average Access Time is   :    39.06250     msec
Average Transfer Rate is :    300.7037     KB/Sec
Average Controller/Vms Overhead is:    6.566970     msec


As you can see the throughput, in Kilobytes/sec, is drastically different for a
"local" disk vs. a "served" disk.

I looked at the code and saw that it was doing random reads to compute the
throughput and that may be causing the MSCP cache to be flushed excessively.  I
modified the code to do the random reads and then do 256 sequential reads
(logical blocks 1 - 256).  Due to a crash, I lost that log file but the
throughput numbers were higher but the difference between local and served
disks turned out to be even greater!  For example:

NTCVX1:  DSKA:
THROUGHPUT FOR 256 SEQUENTIAL READS:  500 KB/sec

NTCVX3:  DSKA:
THROUGHPUT FOR 256 SEQUENTIAL READS:  156 KB/SEC


NTCVX1:  DSKJ:
THROUGHPUT FOR 256 SEQUENTIAL READS:  300 KB/SEC

NTCVX3:  DSKJ:
THROUGHPUT FOR 256 SEQUENTIAL READS:  750 KB/SEC

Clearly, based on this test, local disks win hands down in the throughput race.
But my question/problem is:  Even with sequential QIO's, am I bypassing, and/or
flushing the MSCP cache?  If so, how should I modify VDBM so that I can
effectively test MSCP caching?  And if I am not bypassing and/or flushing the
cache,  How do you explain the performance difference when MSCP caching is
suppose to "buy" us so much?

                            ---------------------

                     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                             Original VDBM code:
                     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


	PROGRAM VDBM
C
C       -------------------------------------------------------------------
C       VDBM -- VAX DISK BENCHMARK V1.0
C
C       Copyright(C), 1988, Bynon & Associates -- All Rights Reserved
C
C       This program may be freely copied and used for non-profit
C       purposes. David W. Bynon shall not be responsible for damages or
C       loss of data due to the incorrect use of this software.
C       -------------------------------------------------------------------
C
	IMPLICIT                   INTEGER(A-Z)
	INCLUDE           '($IODEF)'
	INCLUDE           '($SSDEF)'
	INCLUDE           '($DVIDEF)'
	REAL              MTH$RANDOM, SECONDS, KILOBYTES, AAT, 
	2                 DIFF, SECTORS, REV
	INTEGER*2                  IOSB(4), STATUS, CHANNEL, OFFSET, LENC
	INTEGER*4                  ELAPSED_TIME(2), SEED(2),
	2                 LOGICAL_BLOCK(256), NUMBER_BYTES(256),
	2                 BUFFER(16384), GETDVI, MAXBLOCK, TOTAL_BYTES
	CHARACTER*40      DEVICE
	PARAMETER         (MAXREAD=16384)
C
C Sign on message
C
	TYPE *, 'VAX Disk BenchMark V1.0-1'
C
C Check command line for device name (parameter)
C





	STATUS = LIB$GET_FOREIGN(DEVICE)
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C If the parameter is absent then prompt for it
C
	IF(DEVICE .EQ. ' ') THEN
	  TYPE *,'_Disk: '
	  ACCEPT *, DEVICE
	END IF
C
C If the colon was left off the device name add it
C
	IF(INDEX(DEVICE, ':') .EQ. 0) 
	2  DEVICE(1:40)=DEVICE(1:LENC(DEVICE))//':'
	TYPE *,'Working on...............: ',DEVICE
C
C Use GETDVI function to get the number of blocks on this volume
C
	MAXBLOCK = GETDVI(DEVICE, DVI$_MAXBLOCK)
C
C Get the current time to use as a seed for the random number generator
C       
	STATUS = SYS$GETTIM(SEED)
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C 
C Initialize disk block random read locations
C
	DO I = 1,256
	   LOGICAL_BLOCK(I)=(MTH$RANDOM(SEED)*MAXBLOCK)
	END DO
C
C Assign a device channel for use with $QIO
C
	STATUS = SYS$ASSIGN(DEVICE, CHANNEL,,)
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C--------------------------------------------------------------------------
C Start the average access test (256 iterations)
C--------------------------------------------------------------------------
C
C 
C Initialize and start a timer
C
	STATUS = LIB$INIT_TIMER()
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
	DO I = 1,256
	  STATUS=SYS$QIOW(,%VAL(CHANNEL),            ! Disk I/O channel         
	2                 %VAL(IO$_READLBLK),        ! QIO function (read block)
	2                 IOSB,,,           ! I/O Status block
	2                 BUFFER,           ! Read buffer (p1)
	2                 %VAL(2),          ! Bytes to be read (p2)
	2                 %VAL(LOGICAL_BLOCK(I)),,,) ! Logical block # (p3)
	  IF(.NOT. IOSB(1)) CALL LIB$SIGNAL(%VAL(IOSB(1)))
	  IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
	END DO
C
C Stop the timer
C
	STATUS = LIB$STAT_TIMER(1,ELAPSED_TIME)
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Calculate the drives average access time (The elapsed time, in system 
C delta time format, is expressed in 100-nanosecond units as a
C negative value.)
C
	SECONDS = (ABS(ELAPSED_TIME(1)/10000000))
	AAT = ((SECONDS*1000)/256) 
C	WRITE(UNIT=*, ERR=999, FMT='(1X,A23,F5.1,A5)')
C	2     'AVERAGE ACCESS TIME IS ',AAT,' msec'
	TYPE *,'Average Access Time is   : ',AAT,' msec'
C
C--------------------------------------------------------------------------
C Begin the Random Read Test
C--------------------------------------------------------------------------
C
C Initialize array of random read block size
C
	TOTAL_BYTES=0
	DO I = 1,256
	  NUMBER_BYTES(I) = (MTH$RANDOM(SEED)*MAXREAD)
	  NUMBER_BYTES(I) = (NUMBER_BYTES(I)*4)
	  TOTAL_BYTES = TOTAL_BYTES + NUMBER_BYTES(I)
	END DO
	KILOBYTES = (TOTAL_BYTES/1024)
C 
C Initialize and start a timer
C
	STATUS = LIB$INIT_TIMER()
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Start the random read test (256 iterations)
C
	DO I = 1,256
	  STATUS=SYS$QIOW(,%VAL(CHANNEL),            ! Disk I/O channel         
	2                 %VAL(IO$_READLBLK),        ! QIO function (read block)
	2                 IOSB,,,           ! I/O Status block
	2                 BUFFER,           ! Read buffer (p1)
	2                 %VAL(NUMBER_BYTES(I)),     ! Bytes to be read (p2)
	2                 %VAL(LOGICAL_BLOCK(I)),,,) ! Logical block # (p3)





C
	  IF(.NOT. IOSB(1)) CALL LIB$SIGNAL(%VAL(IOSB(1)))
	  IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
	END DO                                       
C
C Stop the timer
C
	STATUS = LIB$STAT_TIMER(1,ELAPSED_TIME)
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Calculate the drives average throughput rate
C
	SECONDS = (ABS(ELAPSED_TIME(1)/10000000))
c	WRITE(UNIT=*, ERR=999, FMT='(1X,A24,F7.2,A7)')
c	2  'AVERAGE TRANSFER RATE IS',(KILOBYTES/SECONDS),' KB/Sec'
	TYPE *,'Average Transfer Rate is : ',(KILOBYTES/SECONDS),' KB/Sec'
C
C--------------------------------------------------------------------------
C Begin the Controller/VMS overhead test
C--------------------------------------------------------------------------
C
	AAT = 16.67                ! Disk revolution time
	OFFSET = 1
	DO WHILE (AAT .GT. 9)      ! Half revolution access = 8.33 msec
	  OFFSET = OFFSET+1
	  IF ((OFFSET .GT. 8) .AND. (AAT .GT. 16)) THEN
	     TYPE *,'VMS controller overhead cannot be computed.'
	     REV = (AAT/16.67)
	     TYPE *,'The last access was made in',REV,'disk revolutions.'
	     CALL EXIT
	  END IF
C
C Initialize and start a timer
C
	  STATUS = LIB$INIT_TIMER()
	  IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Start the offset read loop
C
	  DO I = 1,128
C
C Block zero read
C
	    STATUS=SYS$QIOW(,%VAL(CHANNEL),%VAL(IO$_READLBLK),
	2                   IOSB,,,BUFFER,%VAL(2),%VAL(0),,,)
	    IF(.NOT. IOSB(1)) CALL LIB$SIGNAL(%VAL(IOSB(1)))
	    IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Offset read
C
	    STATUS=SYS$QIOW(,%VAL(CHANNEL),%VAL(IO$_READLBLK),
	2                   IOSB,,,BUFFER,%VAL(2),%VAL(OFFSET),,,)
	    IF(.NOT. IOSB(1)) CALL LIB$SIGNAL(%VAL(IOSB(1)))
	    IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
	  END DO
C
C Stop the timer
C
	  STATUS = LIB$STAT_TIMER(1,ELAPSED_TIME)
	  IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Calculate the average access time
C
	  SECONDS = (ABS(ELAPSED_TIME(1)/10000000))
	  AAT = (SECONDS*1000)/256
	END DO
C
C OFFSET now represents the lowest number of blocks that must be skipped
C to achieve half revolution access time, i.e., controller/VMS overhead.
C
	SECTORS = GETDVI(DEVICE,DVI$_SECTORS)
	DIFF = OFFSET
C	WRITE(UNIT=*, ERR=999, FMT='(1X,A35,F5.1,A5)')
C	2     'AVERAGE CONTROLLER/VMS OVERHEAD IS ',
C	2     ((DIFF/SECTORS) * 16.67), ' msec'
	TYPE *,'Average Controller/Vms Overhead is: ',((DIFF/SECTORS)*16.67),
	1      ' msec'
C
999	CALL EXIT
	END
 
C       -------------------------------------------------------------------
	INTEGER*4 FUNCTION GETDVI(DEVICE, CODE)
C       -------------------------------------------------------------------
C
C This subroutine is used to return information about the device being
C tested. It must be passed the device name (.e.g., DUA1:, DUB3:...) and
C the $GETDVI code (.e.g., DVI$_????). This routine may only be used if
C the CODE requests an integer value.
C
	IMPLICIT          INTEGER(A-Z)
	INCLUDE           '($DCDEF)'
	INCLUDE           '($SSDEF)'
	INCLUDE           '($DVIDEF)'
C
C GETDVI data structures
C
	STRUCTURE /ITMLST/
	  INTEGER*2                BUFLEN, CODE
	  INTEGER*4                BUFADR, RETLENADR,END_LIST /0/
	END STRUCTURE





	RECORD/ITMLST/ DVI_LIST
	INTEGER*2                  STATUS, CODE
	INTEGER*4                  INFO, INFO_LEN
	CHARACTER*(*)     DEVICE
C
	DVI_LIST.CODE=CODE
	DVI_LIST.BUFLEN=4
	DVI_LIST.BUFADR=%LOC(INFO)
	DVI_LIST.RETLENADR=%LOC(INFO_LEN)
	STATUS = SYS$GETDVIW(,,DEVICE,DVI_LIST,,,,,)
	IF(.NOT. STATUS) THEN
	  CALL LIB$SIGNAL(%VAL(STATUS))
	ELSE
	  GETDVI=INFO
	RETURN
	END IF
	END
 
 
C       -------------------------------------------------------------
	INTEGER FUNCTION LENC(STRING) !Return the length of a string
C       -------------------------------------------------------------
	IMPLICIT INTEGER (A-Z)
	CHARACTER*(*) STRING
 
	LENC = LEN(STRING)
	DO WHILE (STRING(LENC:LENC) .EQ. ' ' .AND. LENC .GT. 1)
	    LENC = LENC - 1
	END DO
	RETURN
	END




                     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                      Modified VDBM for Sequential Reads
                     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

	PROGRAM VDBM
C
C       -------------------------------------------------------------------
C       VDBM -- VAX DISK BENCHMARK V1.0
C
C       Copyright(C), 1988, Bynon & Associates -- All Rights Reserved
C
C       This program may be freely copied and used for non-profit
C       purposes. David W. Bynon shall not be responsible for damages or
C       loss of data due to the incorrect use of this software.
C       -------------------------------------------------------------------
C
	IMPLICIT                   INTEGER(A-Z)
	INCLUDE           '($IODEF)'
	INCLUDE           '($SSDEF)'
	INCLUDE           '($DVIDEF)'
	REAL              MTH$RANDOM, SECONDS, KILOBYTES, AAT, 
	2                 DIFF, SECTORS, REV
	INTEGER*2                  IOSB(4), STATUS, CHANNEL, OFFSET, LENC
	INTEGER*4                  ELAPSED_TIME(2), SEED(2),
	2                 LOGICAL_BLOCK(256), NUMBER_BYTES(256),
	2                 BUFFER(16384), GETDVI, MAXBLOCK, TOTAL_BYTES,
	1		  SEQ_LIST(256)
	CHARACTER*40      DEVICE
	PARAMETER         (MAXREAD=16384)
C
C Sign on message
C
	TYPE *, 'VAX Disk BenchMark V1.0-1'
C
C Check command line for device name (parameter)
C





	STATUS = LIB$GET_FOREIGN(DEVICE)
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C If the parameter is absent then prompt for it
C
	IF(DEVICE .EQ. ' ') THEN
	  TYPE *,'_Disk: '
	  ACCEPT *, DEVICE
	END IF
C
C If the colon was left off the device name add it
C
	IF(INDEX(DEVICE, ':') .EQ. 0) 
	2  DEVICE(1:40)=DEVICE(1:LENC(DEVICE))//':'
	TYPE *,'Working on...............: ',DEVICE
C
C Use GETDVI function to get the number of blocks on this volume
C
	MAXBLOCK = GETDVI(DEVICE, DVI$_MAXBLOCK)
C
C Get the current time to use as a seed for the random number generator
C       
	STATUS = SYS$GETTIM(SEED)
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C 
C Initialize disk block random read locations
C
	DO I = 1,256
	   LOGICAL_BLOCK(I)=(MTH$RANDOM(SEED)*MAXBLOCK)
	   SEQ_LIST(I) = I  !set up a list of sequential logical blocks
	END DO
C
C Assign a device channel for use with $QIO
C
	STATUS = SYS$ASSIGN(DEVICE, CHANNEL,,)
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C--------------------------------------------------------------------------
C Start the average access test (256 iterations)
C--------------------------------------------------------------------------
C
C 
C Initialize and start a timer
C
	STATUS = LIB$INIT_TIMER()
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
	DO I = 1,256
	  STATUS=SYS$QIOW(,%VAL(CHANNEL),            ! Disk I/O channel         
	2                 %VAL(IO$_READLBLK),        ! QIO function (read block)
	2                 IOSB,,,           ! I/O Status block
	2                 BUFFER,           ! Read buffer (p1)
	2                 %VAL(2),          ! Bytes to be read (p2)
	2                 %VAL(LOGICAL_BLOCK(I)),,,) ! Logical block # (p3)
	  IF(.NOT. IOSB(1)) CALL LIB$SIGNAL(%VAL(IOSB(1)))
	  IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
	END DO
C
C Stop the timer
C
	STATUS = LIB$STAT_TIMER(1,ELAPSED_TIME)
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Calculate the drives average access time (The elapsed time, in system 
C delta time format, is expressed in 100-nanosecond units as a
C negative value.)
C
	SECONDS = (ABS(ELAPSED_TIME(1)/10000000))
	AAT = ((SECONDS*1000)/256) 
C	WRITE(UNIT=*, ERR=999, FMT='(1X,A23,F5.1,A5)')
C	2     'AVERAGE ACCESS TIME IS ',AAT,' msec'
	TYPE *,'Average Access Time is   : ',AAT,' msec'
C
C--------------------------------------------------------------------------
C Begin the Random Read Test
C--------------------------------------------------------------------------
C
C Initialize array of random read block size
C
	TOTAL_BYTES=0
	DO I = 1,256
	  NUMBER_BYTES(I) = (MTH$RANDOM(SEED)*MAXREAD)
	  NUMBER_BYTES(I) = (NUMBER_BYTES(I)*4)
	  TOTAL_BYTES = TOTAL_BYTES + NUMBER_BYTES(I)
	END DO
	KILOBYTES = (TOTAL_BYTES/1024)
C 
C Initialize and start a timer
C
	STATUS = LIB$INIT_TIMER()
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Start the random read test (256 iterations)
C
	DO I = 1,256
	  STATUS=SYS$QIOW(,%VAL(CHANNEL),            ! Disk I/O channel         
	2                 %VAL(IO$_READLBLK),        ! QIO function (read block)
	2                 IOSB,,,           ! I/O Status block
	2                 BUFFER,           ! Read buffer (p1)
	2                 %VAL(NUMBER_BYTES(I)),     ! Bytes to be read (p2)
	2                 %VAL(LOGICAL_BLOCK(I)),,,) ! Logical block # (p3)





C
	  IF(.NOT. IOSB(1)) CALL LIB$SIGNAL(%VAL(IOSB(1)))
	  IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
	END DO                                       
C
C Stop the timer
C
	STATUS = LIB$STAT_TIMER(1,ELAPSED_TIME)
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Calculate the drives average throughput rate
C
	SECONDS = (ABS(ELAPSED_TIME(1)/10000000))
c	WRITE(UNIT=*, ERR=999, FMT='(1X,A24,F7.2,A7)')
c	2  'AVERAGE TRANSFER RATE IS',(KILOBYTES/SECONDS),' KB/Sec'
	TYPE *,'Average Transfer Rate(for Random Read) is : ',(KILOBYTES/SECONDS),' KB/Sec'
C
C------------------------------------------------------------------------------------------
c
c  Now do the SEQUENTIAL READS
	TOTAL_BYTES=0
	DO I = 1,256
	  NUMBER_BYTES(I) = (MTH$RANDOM(SEED)*MAXREAD)
	  NUMBER_BYTES(I) = (NUMBER_BYTES(I)*4)
	  TOTAL_BYTES = TOTAL_BYTES + NUMBER_BYTES(I)
	END DO
	KILOBYTES = (TOTAL_BYTES/1024)
C 
C Initialize and start a timer
C
	STATUS = LIB$INIT_TIMER()
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Start the random read test (256 iterations)
C
	DO I = 1,256
	  STATUS=SYS$QIOW(,%VAL(CHANNEL),            ! Disk I/O channel         
	2                 %VAL(IO$_READLBLK),        ! QIO function (read block)
	2                 IOSB,,,           ! I/O Status block
	2                 BUFFER,           ! Read buffer (p1)
	2                 %VAL(NUMBER_BYTES(I)),     ! Bytes to be read (p2)
	2                 %VAL(SEQ_LIST(I)),,,) ! Logical block # (p3)





C
	  IF(.NOT. IOSB(1)) CALL LIB$SIGNAL(%VAL(IOSB(1)))
	  IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
	END DO                                       
C
C Stop the timer
C
	STATUS = LIB$STAT_TIMER(1,ELAPSED_TIME)
	IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Calculate the drives average throughput rate
C
	SECONDS = (ABS(ELAPSED_TIME(1)/10000000))
c	WRITE(UNIT=*, ERR=999, FMT='(1X,A24,F7.2,A7)')
c	2  'AVERAGE TRANSFER RATE IS',(KILOBYTES/SECONDS),' KB/Sec'
	TYPE *,'Average Transfer Rate(for Seq. Read) is : ',(KILOBYTES/SECONDS),' KB/Sec'
C
C--------------------------------------------------------------------------
C Begin the Controller/VMS overhead test
C--------------------------------------------------------------------------
C
	AAT = 16.67                ! Disk revolution time
	OFFSET = 1
	DO WHILE (AAT .GT. 9)      ! Half revolution access = 8.33 msec
	  OFFSET = OFFSET+1
	  IF ((OFFSET .GT. 8) .AND. (AAT .GT. 16)) THEN
	     TYPE *,'VMS controller overhead cannot be computed.'
	     REV = (AAT/16.67)
	     TYPE *,'The last access was made in',REV,'disk revolutions.'
	     CALL EXIT
	  END IF
C
C Initialize and start a timer
C
	  STATUS = LIB$INIT_TIMER()
	  IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Start the offset read loop
C
	  DO I = 1,128
C
C Block zero read
C
	    STATUS=SYS$QIOW(,%VAL(CHANNEL),%VAL(IO$_READLBLK),
	2                   IOSB,,,BUFFER,%VAL(2),%VAL(0),,,)
	    IF(.NOT. IOSB(1)) CALL LIB$SIGNAL(%VAL(IOSB(1)))
	    IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Offset read
C
	    STATUS=SYS$QIOW(,%VAL(CHANNEL),%VAL(IO$_READLBLK),
	2                   IOSB,,,BUFFER,%VAL(2),%VAL(OFFSET),,,)
	    IF(.NOT. IOSB(1)) CALL LIB$SIGNAL(%VAL(IOSB(1)))
	    IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
	  END DO
C
C Stop the timer
C
	  STATUS = LIB$STAT_TIMER(1,ELAPSED_TIME)
	  IF(.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Calculate the average access time
C
	  SECONDS = (ABS(ELAPSED_TIME(1)/10000000))
	  AAT = (SECONDS*1000)/256
	END DO
C
C OFFSET now represents the lowest number of blocks that must be skipped
C to achieve half revolution access time, i.e., controller/VMS overhead.
C
	SECTORS = GETDVI(DEVICE,DVI$_SECTORS)
	DIFF = OFFSET
C	WRITE(UNIT=*, ERR=999, FMT='(1X,A35,F5.1,A5)')
C	2     'AVERAGE CONTROLLER/VMS OVERHEAD IS ',
C	2     ((DIFF/SECTORS) * 16.67), ' msec'
	TYPE *,'Average Controller/Vms Overhead is: ',((DIFF/SECTORS)*16.67),
	1      ' msec'
C
999	CALL EXIT
	END
 
C       -------------------------------------------------------------------
	INTEGER*4 FUNCTION GETDVI(DEVICE, CODE)
C       -------------------------------------------------------------------
C
C This subroutine is used to return information about the device being
C tested. It must be passed the device name (.e.g., DUA1:, DUB3:...) and
C the $GETDVI code (.e.g., DVI$_????). This routine may only be used if
C the CODE requests an integer value.
C
	IMPLICIT          INTEGER(A-Z)
	INCLUDE           '($DCDEF)'
	INCLUDE           '($SSDEF)'
	INCLUDE           '($DVIDEF)'
C
C GETDVI data structures
C
	STRUCTURE /ITMLST/
	  INTEGER*2                BUFLEN, CODE
	  INTEGER*4                BUFADR, RETLENADR,END_LIST /0/
	END STRUCTURE





	RECORD/ITMLST/ DVI_LIST
	INTEGER*2                  STATUS, CODE
	INTEGER*4                  INFO, INFO_LEN
	CHARACTER*(*)     DEVICE
C
	DVI_LIST.CODE=CODE
	DVI_LIST.BUFLEN=4
	DVI_LIST.BUFADR=%LOC(INFO)
	DVI_LIST.RETLENADR=%LOC(INFO_LEN)
	STATUS = SYS$GETDVIW(,,DEVICE,DVI_LIST,,,,,)
	IF(.NOT. STATUS) THEN
	  CALL LIB$SIGNAL(%VAL(STATUS))
	ELSE
	  GETDVI=INFO
	RETURN
	END IF
	END
 
 
C       -------------------------------------------------------------
	INTEGER FUNCTION LENC(STRING) !Return the length of a string
C       -------------------------------------------------------------
	IMPLICIT INTEGER (A-Z)
	CHARACTER*(*) STRING
 
	LENC = LEN(STRING)
	DO WHILE (STRING(LENC:LENC) .EQ. ' ' .AND. LENC .GT. 1)
	    LENC = LENC - 1
	END DO
	RETURN
	END


