/* **++ ** FACILITY: DISKPERF ** ** MODULE DESCRIPTION: ** ** Programme d'evaluation des performances sous-systeme disques ** ** AUTHORS: ** ** JFP. - PiƩronne JF (jf.pieronne@laposte.net) ** ** CREATION DATE: 9-Nov-1995 ** ** DESIGN ISSUES: ** ** x ** ** VERSION: ** ** 1.0 ** ** ** MODIFICATION HISTORY: ** ** Date | Name | Description **----------------+-------+----------------------------------------------------- ** 9-Nov-1995 | JFP | Version initial **----------------+-------+----------------------------------------------------- ** 9-Nov-1995 | GC | Ajout info dans fichier resultats **----------------+-------+----------------------------------------------------- ** 20-Jul-2002 | JFP | Correction creation fichiers pour test multi-disques **----------------+-------+----------------------------------------------------- ** 15-Jun-2006 | JFP | Message d'utilisation fichier pour tests en R/W ** | | changement FAB$M_CTG en FAB$M_CBT **----------------+-------+----------------------------------------------------- ** **-- */ /* compilation : vax : cc/decc diskperf cc/vaxc diskperf axp : cc/prefix=all diskperf -*/ /* ** INCLUDE FILES **/ #ifndef __NEW_STARLET #define __NEW_STARLET #endif #include <climsgdef.h> #include <dcdef.h> #include <descrip.h> #include <dvidef.h> #include <fibdef.h> #include <gen64def.h> #include <iledef.h> #include <iodef.h> #include <iosbdef.h> #include <lib$routines.h> #include <libwaitdef.h> #include <rms.h> #include <rmsdef.h> #include <ssdef.h> #include <starlet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stsdef.h> #include <unixio.h> #include <unixlib.h> #define K_DisksCard 10 #define K_MaxSimQIO 200 /* VMS pre 6.0 */ #ifndef IO$M_NOVCACHE #define IO$M_NOVCACHE 0x20000 #endif #ifdef IN_VSCODE # define _align(n) #endif typedef struct { int _IOCount; int _ReadIOCount; int _WriteIOCount; int _elapsed[2]; unsigned int _cpu; } Stat_s; static enum _tt { KReadOnly = 0, KWriteOnly = 1, KReadWrite = 2 } TypeTest; static enum _ts { KDuration = 0, KIOCount = 1, KSize = 2 } TypeStop; volatile static long ReadCount; volatile static long WriteCount; static long CacheHitPercent; static long ReadPercent; static int StartingBlock; static int EndingBlock; static int Random; static int Pass; static int Interval; volatile static int TotIO; volatile static ReadIOCount; volatile static WriteIOCount; volatile static EndPass; volatile static ActiveIOCount = 0; static int SimultaneousIO; static int MinIOSize; static int MaxIOSize; static int ReadIOSize; static int WriteIOSize; static double ReadWriteIOSizeRatio; static int PassDuration; static int TotSize; static int VioModifier; static IOSB Iosb[K_MaxSimQIO]; static int DisksCount; static char FullDevnam[K_DisksCard][65], Medianam[K_DisksCard][65]; static char Volnam[K_DisksCard][13]; static unsigned short Channel[K_DisksCard]; volatile static int Address[K_DisksCard]; Stat_s StatInfo[8][127]; /* 8 pass 1-127 blocks */ static char FileName[K_DisksCard][256]; static FIBDEF Fib[K_DisksCard]; static _align(PAGE) char IOBuffer[K_MaxSimQIO][512 * 127]; /* buffer size 127 blocks maximum */ static void IOCompletionAST(int); /* * -- DCL callback interface */ extern int cli$get_value(struct dsc$descriptor_s *, struct dsc$descriptor_s *, short *); extern int cli$present(struct dsc$descriptor_s *); /* * -- RTL string routines */ extern int str$free1_dx(struct dsc$descriptor_s *); static int YesOrNo(const char *str) { int rep = 2; while ((rep != 0) && (rep != 1)) { printf("%s", str); scanf("%d", &rep); } return rep; } static void InteractiveQueries() { int i; printf("\nTest type (0 : Read only, 1 : Write only, 2 : Read-Write): "); scanf("%d", &i); TypeTest = (enum _tt)i; if (TypeTest == KReadWrite) { printf("\nRead percent: "); scanf("%d", &ReadPercent); printf("\n(Read Size / Write Size) Ratio: "); scanf("%lf", &ReadWriteIOSizeRatio); } #ifdef FullInteractive printf("\n# disks (1 - 10): "); scanf("%d", &DisksCount); getchar(); if (DisksCount > K_DisksCard) exit(SS$_ABORT); for (i = 0; i < DisksCount; ++i) { int classDisk, opcnt, max, free; int hoav; int status; unsigned short devlen; unsigned short volnamlen, medialen; int freebl, fp, ip, catchup, merge, member, fail, refcnt; int errcnt; char devnam[65]; ILE3 gds[] = {{4, DVI$_DEVCLASS, &classDisk, 0}, {4, DVI$_SHDW_CATCHUP_COPYING, &catchup, 0}, {4, DVI$_SHDW_FAILED_MEMBER, &fail, 0}, {4, DVI$_SHDW_MEMBER, &member, 0}, {4, DVI$_SHDW_MERGE_COPYING, &merge, 0}, {4, DVI$_HOST_AVAIL, &hoav, 0}, {4, DVI$_REFCNT, &refcnt, 0}, {4, DVI$_FREEBLOCKS, &freebl, 0}, {4, DVI$_MAXBLOCK, &max, 0}, {64, DVI$_MEDIA_NAME, Medianam[i], &medialen}, {64, DVI$_FULLDEVNAM, FullDevnam[i], &devlen}, {4, DVI$_OPCNT, &opcnt, 0}, {4, DVI$_ERRCNT, &errcnt, 0}, {12, DVI$_VOLNAM, Volnam[i], &volnamlen}, {0, 0}}; $DESCRIPTOR(devnam_d, devnam); printf("\nDevice name: "); gets(devnam); puts("device name label type # blocks free blocks I/O " " errors"); puts("------------ -------- ---- --------- -------------- " "----------- ------"); devnam_d.dsc$w_length = strlen(devnam); memset(Medianam[i], ' ', sizeof(Medianam[0]) - 1); Medianam[i][sizeof(Medianam[0]) - 1] = '\0'; memset(Volnam[i], ' ', sizeof(Volnam[0]) - 1); Volnam[i][sizeof(Volnam[0]) - 1] = '\0'; memset(FullDevnam[i], ' ', sizeof(FullDevnam[0]) - 1); FullDevnam[i][sizeof(FullDevnam[0]) - 1] = '\0'; status = sys$getdviw(0, 0, &devnam_d, gds, 0, 0, 0, 0); if (!$VMS_STATUS_SUCCESS(status)) exit(status); if ((classDisk != DC$_DISK) || !hoav || member || fail || catchup || merge || (refcnt == 0)) exit(SS$_ABORT); if (max == 0) exit(SS$_ABORT); // FullDevnam[i][14] = '\0'; // Volnam[i][9] = '\0'; // Medianam[i][6] = '\0'; fp = 100.0 * (double)freebl / (double)max; printf("%-13s %-9s %-6s%9d%9d (%3d%%) %9d %6d\n", &FullDevnam[i][1], Volnam[i], Medianam[i], max, freebl, fp, opcnt, errcnt); } #endif printf("\nStarting block: "); scanf("%d", &StartingBlock); printf("\nEnding block: "); scanf("%d", &EndingBlock); Random = YesOrNo("\nRandom (0/1): "); if (!Random) { printf("\nInterval (blocks -1 : use IO size): "); scanf("%d", &Interval); } VioModifier = YesOrNo("\nVirtual I/O Cache (0/1): ") ? 0 : IO$M_NOVCACHE; printf("\nEstimate cache hit percent"); if ((EndingBlock - StartingBlock) < 1000000) printf(" (may not be significant): "); else printf(": "); scanf("%d", &CacheHitPercent); printf("\nPass (8 max): "); scanf("%d", &Pass); printf("\nStop on (0 : Duration, 1 : IOs Count, 2 : Total Size): "); scanf("%d", &i); TypeStop = (enum _ts)i; switch (TypeStop) { case KDuration: printf("\nPass Duration: "); scanf("%d", &PassDuration); break; case KIOCount: printf("\nTotal IOs count: "); scanf("%d", &TotIO); break; case KSize: printf("\nTotal Size (Kbytes): "); scanf("%d", &TotSize); break; default: fprintf(stderr, "\nInvalid stop switch\n"); exit(SS$_ABORT); } printf("\nSimultaneous IOs count (%d max): ", K_MaxSimQIO / DisksCount); scanf("%d", &SimultaneousIO); if (SimultaneousIO * DisksCount > K_MaxSimQIO) exit(SS$_ABORT); printf("\nMin IO size (1-127 blocks): "); scanf("%d", &MinIOSize); printf("\nMax IO size (%d-127 blocks): ", MinIOSize); scanf("%d", &MaxIOSize); } /* * * CLI interface * */ static void ProcessCommandLine() { $DESCRIPTOR(interactiveQualDesc, "INTERACTIVE"); $DESCRIPTOR(sequentialQualDesc, "SEQUENTIAL"); $DESCRIPTOR(seqIntervalQualDesc, "SEQUENTIAL.INTERVAL"); $DESCRIPTOR(disksQualDesc, "DISKS"); $DESCRIPTOR(typeReadQualDesc, "TYPE.READ"); $DESCRIPTOR(typeWriteQualDesc, "TYPE.WRITE"); $DESCRIPTOR(typeRatioQualDesc, "TYPE.RATIO"); $DESCRIPTOR(rangeStartQualDesc, "RANGE.START"); $DESCRIPTOR(rangeSizeQualDesc, "RANGE.SIZE"); $DESCRIPTOR(cacheQualDesc, "CACHE"); $DESCRIPTOR(VIOCacheQualDesc, "VIOCACHE"); $DESCRIPTOR(cachePercentQualDesc, "CACHE.PERCENT"); $DESCRIPTOR(passQualDesc, "PASS"); $DESCRIPTOR(EndIOQualDesc, "END.IO_COUNT"); $DESCRIPTOR(EndSecondsQualDesc, "END.SECONDS"); $DESCRIPTOR(EndVolumeQualDesc, "END.VOLUME"); $DESCRIPTOR(IOSizeMinQualDesc, "IO_SIZE.MINIMUM"); $DESCRIPTOR(IOSizeMaxQualDesc, "IO_SIZE.MAXIMUM"); $DESCRIPTOR(readWriteRatioSizeQualDesc, "IO_SIZE.RATIO"); $DESCRIPTOR(simultaneousIOQualDesc, "SIMULTANEOUS_IO"); int i; char str[100]; struct dsc$descriptor_s retdesc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_D, NULL}; short retlen; int maxBlock = 0; DisksCount = 0; for (i = 0; $VMS_STATUS_SUCCESS(cli$get_value(&disksQualDesc, &retdesc, &retlen)); ++i) { int classDisk, opcnt, max, free; int hoav; int status; unsigned short devlen; unsigned short volnamlen, medialen; int freebl, fp, ip, catchup, merge, member, fail, refcnt; int errcnt; char devnam[65]; ILE3 gds[] = {{4, DVI$_DEVCLASS, &classDisk, 0}, {4, DVI$_SHDW_CATCHUP_COPYING, &catchup, 0}, {4, DVI$_SHDW_FAILED_MEMBER, &fail, 0}, {4, DVI$_SHDW_MEMBER, &member, 0}, {4, DVI$_SHDW_MERGE_COPYING, &merge, 0}, {4, DVI$_HOST_AVAIL, &hoav, 0}, {4, DVI$_REFCNT, &refcnt, 0}, {4, DVI$_FREEBLOCKS, &freebl, 0}, {4, DVI$_MAXBLOCK, &max, 0}, {64, DVI$_MEDIA_NAME, Medianam[i], &medialen}, {64, DVI$_FULLDEVNAM, FullDevnam[i], &devlen}, {4, DVI$_OPCNT, &opcnt, 0}, {4, DVI$_ERRCNT, &errcnt, 0}, {12, DVI$_VOLNAM, Volnam[i], &volnamlen}, {0, 0}}; $DESCRIPTOR(devnam_d, devnam); ++DisksCount; if (DisksCount > K_DisksCard) exit(SS$_ABORT); strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; strcpy(devnam, str); devnam_d.dsc$w_length = strlen(devnam); memset(Medianam[i], ' ', sizeof(Medianam[0]) - 1); Medianam[i][sizeof(Medianam[0]) - 1] = '\0'; memset(Volnam[i], ' ', sizeof(Volnam[0]) - 1); Volnam[i][sizeof(Volnam[0]) - 1] = '\0'; memset(FullDevnam[i], ' ', sizeof(FullDevnam[0]) - 1); FullDevnam[i][sizeof(FullDevnam[0]) - 1] = '\0'; status = sys$getdviw(0, 0, &devnam_d, gds, 0, 0, 0, 0); if (!$VMS_STATUS_SUCCESS(status)) exit(status); if ((classDisk != DC$_DISK) || !hoav || member || fail || catchup || merge || (refcnt == 0)) exit(SS$_ABORT); if (max == 0) exit(SS$_ABORT); if ((max < maxBlock) || (maxBlock == 0)) maxBlock = max; // FullDevnam[i][14] = '\0'; // Volnam[i][9] = '\0'; // Medianam[i][6] = '\0'; } if ($VMS_STATUS_SUCCESS(cli$present(&interactiveQualDesc))) { InteractiveQueries(); return; } if ($VMS_STATUS_SUCCESS(cli$present(&sequentialQualDesc))) { Random = 0; if ($VMS_STATUS_SUCCESS( cli$get_value(&seqIntervalQualDesc, &retdesc, &retlen))) { strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; sscanf(str, "%d", &Interval); } else Interval = -1; } else Random = 1; if ($VMS_STATUS_SUCCESS(cli$present(&typeReadQualDesc)) && $VMS_STATUS_SUCCESS(cli$present(&typeWriteQualDesc))) { TypeTest = KReadWrite; } else if ($VMS_STATUS_SUCCESS(cli$present(&typeWriteQualDesc))) { TypeTest = KWriteOnly; } else { /* read only */ TypeTest = KReadOnly; } if ($VMS_STATUS_SUCCESS( cli$get_value(&typeRatioQualDesc, &retdesc, &retlen))) { strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; sscanf(str, "%d", &ReadPercent); } else ReadPercent = 80; cli$get_value(&passQualDesc, &retdesc, &retlen); strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; sscanf(str, "%d", &Pass); if ($VMS_STATUS_SUCCESS(cli$present(&rangeStartQualDesc))) { cli$get_value(&rangeStartQualDesc, &retdesc, &retlen); strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; sscanf(str, "%d", &StartingBlock); } else StartingBlock = 1; if ($VMS_STATUS_SUCCESS(cli$present(&rangeSizeQualDesc))) { cli$get_value(&rangeSizeQualDesc, &retdesc, &retlen); strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; sscanf(str, "%d", &EndingBlock); } else EndingBlock = StartingBlock + maxBlock / 3; if ($VMS_STATUS_SUCCESS( cli$get_value(&cachePercentQualDesc, &retdesc, &retlen))) { strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; sscanf(str, "%d", &CacheHitPercent); } else if ($VMS_STATUS_SUCCESS(cli$present(&cacheQualDesc))) CacheHitPercent = 20; else CacheHitPercent = 0; if ($VMS_STATUS_SUCCESS( cli$get_value(&EndVolumeQualDesc, &retdesc, &retlen))) { strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; sscanf(str, "%d", &TotSize); TypeStop = KSize; } else if ($VMS_STATUS_SUCCESS( cli$get_value(&EndIOQualDesc, &retdesc, &retlen))) { strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; sscanf(str, "%d", &TotIO); TypeStop = KIOCount; } else if ($VMS_STATUS_SUCCESS( cli$get_value(&EndSecondsQualDesc, &retdesc, &retlen))) { strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; sscanf(str, "%d", &PassDuration); TypeStop = KDuration; } else { PassDuration = 15; TypeStop = KDuration; } if ($VMS_STATUS_SUCCESS( cli$get_value(&IOSizeMinQualDesc, &retdesc, &retlen))) { strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; sscanf(str, "%d", &MinIOSize); } else MinIOSize = 12; if ($VMS_STATUS_SUCCESS( cli$get_value(&IOSizeMaxQualDesc, &retdesc, &retlen))) { strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; sscanf(str, "%d", &MaxIOSize); } else MaxIOSize = MinIOSize; if ($VMS_STATUS_SUCCESS( cli$get_value(&readWriteRatioSizeQualDesc, &retdesc, &retlen))) { strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; sscanf(str, "%lf", &ReadWriteIOSizeRatio); } else ReadWriteIOSizeRatio = 3; cli$get_value(&simultaneousIOQualDesc, &retdesc, &retlen); strncpy(str, retdesc.dsc$a_pointer, retlen); str[retlen] = '\0'; sscanf(str, "%d", &SimultaneousIO); if (SimultaneousIO * DisksCount > K_MaxSimQIO) exit(SS$_ABORT); if ($VMS_STATUS_SUCCESS(cli$present(&VIOCacheQualDesc))) VioModifier = 0; else VioModifier = IO$M_NOVCACHE; /* * Release the dynamic string we have been using. */ if (retdesc.dsc$a_pointer != NULL) str$free1_dx(&retdesc); } void IoAccess(unsigned short channel, FIBDEF *fib) { IOSB ioFich; long status; struct { unsigned long l; unsigned long adr; } fibDes; fibDes.l = sizeof(*fib); fibDes.adr = (unsigned long)fib; status = sys$qiow(0, channel, IO$_ACCESS | IO$M_ACCESS, &ioFich, 0, 0, &fibDes, 0, 0, 0, 0, 0); if (!$VMS_STATUS_SUCCESS(status)) { fprintf(stderr, "\nIoAccess Error\n"); exit(status); } } void IoDeAccess(unsigned short channel, FIBDEF *fib) { IOSB ioFich; long status; struct { unsigned long l; unsigned long adr; } fibDes; fibDes.l = sizeof(*fib); fibDes.adr = (unsigned long)fib; status = sys$qiow(0, channel, IO$_DEACCESS, &ioFich, 0, 0, &fibDes, 0, 0, 0, 0, 0); if (!$VMS_STATUS_SUCCESS(status)) { fprintf(stderr, "\nIoDeAccess Error %X\n", status); } } static void DeleteFiles() { static done; int i; if (!done) { for (i = 0; i < DisksCount; ++i) { IoDeAccess(Channel[i], &(Fib[i])); delete (FileName[i]); } done = 1; } else { for (i = 0; i < DisksCount; ++i) { delete (FileName[i]); } } } static CreateFile(unsigned short *channel, FIBDEF *fib, char *fileName, long maxVbn) { struct FAB fabFlog; struct RAB rabFlog; long status; struct FAB *fabP = 0; struct NAM *namP; long statRms; char temp[256]; $DESCRIPTOR(tempDesc, temp); $DESCRIPTOR(fichierDesc, fileName); fichierDesc.dsc$w_length = strlen(fileName); fabFlog = cc$rms_fab; rabFlog = cc$rms_rab; fabFlog.fab$l_fna = fileName; fabFlog.fab$b_fns = strlen(fileName); fabFlog.fab$b_org = FAB$C_SEQ; fabFlog.fab$l_alq = maxVbn; fabFlog.fab$b_fac = FAB$M_GET | FAB$M_PUT; fabFlog.fab$b_shr = FAB$M_SHRPUT | FAB$M_SHRGET; fabFlog.fab$l_fop = FAB$M_CBT; fabFlog.fab$w_mrs = 512; status = sys$create(&fabFlog, 0, 0); if (!$VMS_STATUS_SUCCESS(status)) { fprintf(stderr, "\nCreate Error\n"); exit(status); } status = sys$close(&fabFlog, 0, 0); if (!$VMS_STATUS_SUCCESS(status)) { fprintf(stderr, "\nClose Error\n"); exit(status); } fabP = 0; status = lib$find_file(&fichierDesc, &tempDesc, (unsigned int *)&fabP, 0, 0, &statRms, 0); if (!$VMS_STATUS_SUCCESS(status)) { fprintf(stderr, "\nFind File Error\n"); exit(status); } status = sys$assign(&fichierDesc, channel, 0, 0, 0); if (!$VMS_STATUS_SUCCESS(status)) { fprintf(stderr, "\nAssign Error\n"); exit(status); } namP = fabP->fab$l_nam; #if defined(__VAXC) || defined(VAXC) fib->fib$r_fid_overlay.fib$w_fid[0] = namP->nam$w_fid[0]; fib->fib$r_fid_overlay.fib$w_fid[1] = namP->nam$w_fid[1]; fib->fib$r_fid_overlay.fib$w_fid[2] = namP->nam$w_fid[2]; fib->fib$r_acctl_overlay.fib$l_acctl = FIB$M_NOWRITE | FIB$M_WRITE; #else fib->fib$w_fid[0] = namP->nam$w_fid[0]; fib->fib$w_fid[1] = namP->nam$w_fid[1]; fib->fib$w_fid[2] = namP->nam$w_fid[2]; fib->fib$l_acctl = FIB$M_NOWRITE | FIB$M_WRITE; #endif } static void DoIO(int i) { int status; int ioSize; switch (TypeStop) { case KDuration: break; case KIOCount: case KSize: if (TotIO == 0) EndPass = 1; else --TotIO; break; default: fprintf(stderr, "\nInvalid stop switch\n"); exit(SS$_ABORT); } if (!EndPass) { unsigned short channel = Channel[i]; int writeIO; ++ActiveIOCount; if (TypeTest == KReadWrite) { writeIO = (100 * ((double)rand()) / 0x7fffffff) >= ReadPercent; ioSize = writeIO ? WriteIOSize : ReadIOSize; if (writeIO) ++WriteIOCount; else ++ReadIOCount; } else { ioSize = ReadIOSize; ++ReadIOCount; } if ((100 * ((double)rand()) / 0x7fffffff) >= CacheHitPercent) if (Random) Address[i] = StartingBlock + (EndingBlock - StartingBlock) * ((double)rand()) / 0x7fffffff; else { Address[i] += (Interval == -1 ? ioSize : Interval); if (Address[i] + ioSize > EndingBlock) Address[i] = StartingBlock; } switch (TypeTest) { case KReadOnly: status = sys$qio(0, channel, IO$_READLBLK, &Iosb[i], IOCompletionAST, i, IOBuffer[i], 512 * ioSize, Address[i], 0, 0, 0); break; case KWriteOnly: status = sys$qio(0, channel, IO$_WRITEVBLK | VioModifier, &Iosb[i], IOCompletionAST, i, IOBuffer[i], 512 * ioSize, Address[i], 0, 0, 0); break; case KReadWrite: if (writeIO) { ++WriteCount; status = sys$qio(0, channel, IO$_WRITEVBLK | VioModifier, &Iosb[i], IOCompletionAST, i, IOBuffer[i], 512 * ioSize, Address[i], 0, 0, 0); } else { ++ReadCount; status = sys$qio(0, channel, IO$_READVBLK | VioModifier, &Iosb[i], IOCompletionAST, i, IOBuffer[i], 512 * ioSize, Address[i], 0, 0, 0); } break; default: fputs("Invalid test", stderr); exit(SS$_ABORT); } if (!$VMS_STATUS_SUCCESS(status)) exit(status); } else if (ActiveIOCount == 0) { unsigned int pid = getpid(); status = sys$wake(&pid, 0); if (!$VMS_STATUS_SUCCESS(status)) exit(status); } } static void IOCompletionAST(int i) { --ActiveIOCount; DoIO(i); } #ifdef __cplusplus static void TimerAST(...) { #else static void TimerAST() { #endif EndPass = 1; } main() { int status; int i; FILE *fo; printf("%s %s, J.F. Pi?ronne, jf.pieronne@laposte.net\n", __DATE__, __TIME__); ProcessCommandLine(); if (TypeTest != KReadOnly) { int i; atexit(DeleteFiles); for (i = 0; i < DisksCount; ++i) { strcpy(FileName[i], (char *)&FullDevnam[i]); strcat(FileName[i], "[000000]DISKPERF.TMP"); printf("Temporary file used for write perfomance test :\n%s\n", FileName[i]); CreateFile(&(Channel[i]), &(Fib[i]), FileName[i], EndingBlock - StartingBlock + 1); IoAccess(Channel[i], &(Fib[i])); } } else { int i; for (i = 0; i < DisksCount; ++i) { char devnam[65]; $DESCRIPTOR(devnamDesc, devnam); strcpy(devnam, FullDevnam[i]); devnamDesc.dsc$w_length = strlen(devnam); status = sys$assign(&devnamDesc, &(Channel[i]), 0, 0); if (!$VMS_STATUS_SUCCESS(status)) exit(status); } } for (i = 0; i < Pass; ++i) { // float waitTime = 15; // int waitFlags = LIB$K_NOWAKE; for (ReadIOSize = MinIOSize; ReadIOSize <= MaxIOSize; ++ReadIOSize) { Stat_s *sp = &(StatInfo[i][ReadIOSize - 1]); int sio; int tio; int ts; int j; GENERIC_64 deltaTime; ReadIOCount = WriteIOCount = 0; if (TypeTest == KReadWrite) WriteIOSize = ReadIOSize / ReadWriteIOSizeRatio + 0.5; else WriteIOSize = 1; if (WriteIOSize == 0) WriteIOSize = 1; EndPass = 0; switch (TypeStop) { case KDuration: deltaTime.gen64$l_longword[0] = -10000000 * PassDuration; deltaTime.gen64$l_longword[1] = -1; status = sys$setimr(0, &deltaTime, TimerAST, 0, 0); if (!$VMS_STATUS_SUCCESS(status)) exit(status); break; case KIOCount: tio = TotIO; break; case KSize: TotIO = TotSize / ReadIOSize; break; default: fprintf(stderr, "\nInvalid stop switch\n"); exit(SS$_ABORT); } for (j = 0; j < DisksCount; ++j) Address[j] = StartingBlock; lib$init_timer(NULL); status = sys$setast(0); if (!$VMS_STATUS_SUCCESS(status)) exit(status); for (j = 0; j < SimultaneousIO; ++j) { int k; for (k = 0; k < DisksCount; ++k) DoIO(k); } status = sys$setast(1); if (!$VMS_STATUS_SUCCESS(status)) exit(status); while (!EndPass || ActiveIOCount) { status = sys$hiber(); if (!$VMS_STATUS_SUCCESS(status)) exit(status); } j = 2; status = lib$stat_timer(&j, &(sp->_cpu)); if (!$VMS_STATUS_SUCCESS(status)) exit(status); j = 1; status = lib$stat_timer(&j, (unsigned int *)sp->_elapsed); if (!$VMS_STATUS_SUCCESS(status)) exit(status); if (TypeStop == KIOCount) TotIO = tio; StatInfo[i][ReadIOSize - 1]._IOCount = ReadIOCount + WriteIOCount; StatInfo[i][ReadIOSize - 1]._ReadIOCount = ReadIOCount; StatInfo[i][ReadIOSize - 1]._WriteIOCount = WriteIOCount; // lib$wait(&waitTime, &waitFlags); sleep(5); } } fo = fopen("diskperf.lis", "w"); fprintf(fo, "%s and ", TypeTest == KWriteOnly ? "Write" : TypeTest == KReadOnly ? "Read" : "Read-Write"); fputs(Random ? "Random access test\n" : "Sequential access Test\n", fo); fprintf(fo, "Starting block %d, ending block %d, Simultaneous i/o %d\n", StartingBlock, EndingBlock, SimultaneousIO); fprintf(fo, "Giving cache hit percent : %d\n", CacheHitPercent); if (VioModifier || TypeTest == KReadOnly) fprintf(fo, "Virtual IO cache not active\n"); else fprintf(fo, "Virtual IO cache active\n"); if (TypeTest == KReadWrite) fprintf( fo, "Effective read percent : %4.1lf\nRead Size / Write Size : %lf\n", 100 * ((double)ReadCount) / (ReadCount + WriteCount), ReadWriteIOSizeRatio); fputs("device name label type\n", fo); fputs("------------ -------- ----\n", fo); for (i = 0; i < DisksCount; ++i) fprintf(fo, "%-13s %-9s %-6s\n", &(FullDevnam[i][1]), Volnam[i], Medianam[i]); for (ReadIOSize = MinIOSize; ReadIOSize <= MaxIOSize; ++ReadIOSize) { if (TypeTest == KReadWrite) WriteIOSize = ReadIOSize / ReadWriteIOSizeRatio + 0.5; else WriteIOSize = 1; if (WriteIOSize == 0) WriteIOSize = 1; fprintf(fo, "\n!%3d !", ReadIOSize); for (i = 0; i < Pass; ++i) { Stat_s *sp = &(StatInfo[i][ReadIOSize - 1]); fprintf( fo, " %5d IOs %2d ms %4d IO/s %6d KB/s!", sp->_IOCount, -(int)((double)sp->_elapsed[0] / 10000.0 / sp->_IOCount * SimultaneousIO * DisksCount), -(int)((double)(sp->_IOCount) * 10000000.0 / sp->_elapsed[0]), -(int)((double)(sp->_ReadIOCount) * ReadIOSize * 10000000.0 / sp->_elapsed[0] / 2) - (int)((double)(sp->_WriteIOCount) * WriteIOSize * 10000000.0 / sp->_elapsed[0] / 2)); } } fclose(fo); fo = fopen("diskperf.dat", "w"); fprintf(fo, "Size\tIOs\tService\tIO/s\tKB/s"); for (ReadIOSize = MinIOSize; ReadIOSize <= MaxIOSize; ++ReadIOSize) { double ioc = 0, ser = 0, ios = 0, kbs = 0; for (i = 0; i < Pass; ++i) { Stat_s *sp = &(StatInfo[i][ReadIOSize - 1]); ioc += sp->_IOCount; ser += -(double)sp->_elapsed[0] / 10000.0 / sp->_IOCount * SimultaneousIO * DisksCount; ios += -(int)((double)(sp->_IOCount) * 10000000.0 / sp->_elapsed[0]); kbs += -(int)((double)(sp->_ReadIOCount) * ReadIOSize * 10000000.0 / sp->_elapsed[0] / 2) - (int)((double)(sp->_WriteIOCount) * WriteIOSize * 10000000.0 / sp->_elapsed[0] / 2); } ioc /= Pass; ser /= Pass; ios /= Pass; kbs /= Pass; fprintf(fo, "\n%3d\t%d\t%d\t%d\t%d", ReadIOSize, (int)ioc, (int)ser, (int)ios, (int)kbs); /* for(i = 0; i < Pass; ++i) { Stat_s* sp = &(StatInfo[i][ReadIOSize - 1]); fprintf(fo, "\t%5d\t%2d\t%4d\t%4d", sp->_IOCount, - (int)((double)sp->_elapsed[0] / 10000.0 / sp->_IOCount * SimultaneousIO * DisksCount), - (int)((double)(sp->_IOCount) * 10000000.0 / sp->_elapsed[0]), - (int)((double)(sp->_ReadIOCount) * 10000000.0 / sp->_elapsed[0] * ReadIOSize / 2) - (int)((double)(sp->_WriteIOCount) * 10000000.0 / sp->_elapsed[0] * WriteIOSize / 2)); } */ } fclose(fo); }