VirtualBox

Changeset 80065 in vbox for trunk/src


Ignore:
Timestamp:
Jul 31, 2019 11:04:15 AM (5 years ago)
Author:
vboxsync
Message:

ValidationKit/IoPerf: Updates to the core test loop

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/utils/storage/IoPerf.cpp

    r80032 r80065  
    5757*********************************************************************************************************************************/
    5858
     59/** Size multiplier for the random data buffer to seek around. */
     60#define IOPERF_RAND_DATA_BUF_FACTOR 3
     61
    5962
    6063/*********************************************************************************************************************************
     
    104107    IOPERFTESTSETPREP_32BIT_HACK = 0x7fffffff
    105108} IOPERFTESTSETPREP;
     109
     110
     111/**
     112 * I/O perf request.
     113 */
     114typedef struct IOPERFREQ
     115{
     116    /** Start timestamp. */
     117    uint64_t                    tsStart;
     118    /** Request operation code. */
     119    RTIOQUEUEOP                 enmOp;
     120    /** Start offset. */
     121    uint64_t                    offXfer;
     122    /** Transfer size for the request. */
     123    size_t                      cbXfer;
     124    /** The buffer used for the transfer. */
     125    void                        *pvXfer;
     126    /** This is the statically assigned destination buffer for read requests for this request. */
     127    void                        *pvXferRead;
     128    /** Size of the read buffer. */
     129    size_t                      cbXferRead;
     130} IOPERFREQ;
     131/** Pointer to an I/O perf request. */
     132typedef IOPERFREQ *PIOPERFREQ;
     133/** Pointer to a constant I/O perf request. */
     134typedef const IOPERFREQ *PCIOPERFREQ;
    106135
    107136
     
    133162    /** Maximum number of requests to queue. */
    134163    uint32_t                    cReqsMax;
     164    /** Pointer to the array of request specific data. */
     165    PIOPERFREQ                  paIoReqs;
     166    /** Page aligned chunk of memory assigned as read buffers for the individual requests. */
     167    void                        *pvIoReqReadBuf;
     168    /** Size of the read memory buffer. */
     169    size_t                      cbIoReqReadBuf;
     170    /** Random number generator used. */
     171    RTRAND                      hRand;
     172    /** The random data buffer used for writes. */
     173    uint8_t                     *pbRandWrite;
     174    /** Size of the random write buffer in 512 byte blocks. */
     175    uint32_t                    cRandWriteBlocks512B;
    135176    /** Test dependent data. */
    136177    union
    137178    {
    138         uint32_t                uDummy;
     179        /** Sequential read write. */
     180        uint64_t                offNextSeq;
    139181    } Tst;
    140182} IOPERFJOB;
     
    191233    { "--dir",                      'd',                            RTGETOPT_REQ_STRING  },
    192234    { "--relative-dir",             'r',                            RTGETOPT_REQ_NOTHING },
    193     { "--enable-all",               'e',                            RTGETOPT_REQ_NOTHING },
    194     { "--disable-all",              'z',                            RTGETOPT_REQ_NOTHING },
    195235
    196236    { "--jobs",                     'j',                            RTGETOPT_REQ_UINT32  },
     
    198238    { "--test-set-size",            's',                            RTGETOPT_REQ_UINT64  },
    199239    { "--block-size",               'b',                            RTGETOPT_REQ_UINT32  },
     240    { "--maximum-requests",         'm',                            RTGETOPT_REQ_UINT32  },
    200241
    201242    { "--first-write",              kCmdOpt_FirstWrite,             RTGETOPT_REQ_NOTHING },
     
    280321 * @return Next test to run.
    281322 */
    282 static IOPERFTEST ioPerfTestSelectNext()
     323static IOPERFTEST ioPerfJobTestSelectNext()
    283324{
    284325    AssertReturn(g_idxTest < RT_ELEMENTS(g_aenmTests), IOPERFTEST_SHUTDOWN);
    285326
    286327    while (   g_idxTest < RT_ELEMENTS(g_aenmTests)
    287            && g_aenmTests[g_idxTest] != IOPERFTEST_DISABLED)
     328           && g_aenmTests[g_idxTest] == IOPERFTEST_DISABLED)
    288329        g_idxTest++;
    289330
     
    291332
    292333    return g_aenmTests[g_idxTest];
     334}
     335
     336
     337/**
     338 * Returns the I/O queue operation for the next request.
     339 *
     340 * @returns I/O queue operation enum.
     341 * @param   pJob                The job data for the current worker.
     342 */
     343static RTIOQUEUEOP ioPerfJobTestGetIoQOp(PIOPERFJOB pJob)
     344{
     345    switch (pJob->enmTest)
     346    {
     347        case IOPERFTEST_FIRST_WRITE:
     348        case IOPERFTEST_SEQ_WRITE:
     349        case IOPERFTEST_SEQ_READ:
     350        case IOPERFTEST_REV_WRITE:
     351        case IOPERFTEST_RND_WRITE:
     352            return RTIOQUEUEOP_WRITE;
     353
     354        case IOPERFTEST_RND_READ:
     355        case IOPERFTEST_REV_READ:
     356            return RTIOQUEUEOP_READ;
     357        case IOPERFTEST_SEQ_READWRITE:
     358        case IOPERFTEST_RND_READWRITE:
     359            AssertMsgFailed(("Not implemented!\n"));
     360            break;
     361        default:
     362            AssertMsgFailed(("Invalid/unknown test selected: %d\n", pJob->enmTest));
     363            break;
     364    }
     365
     366    return RTIOQUEUEOP_INVALID;
     367}
     368
     369
     370/**
     371 * Returns the offset to use for the next request.
     372 *
     373 * @returns Offset to use.
     374 * @param   pJob                The job data for the current worker.
     375 */
     376static uint64_t ioPerfJobTestGetOffsetNext(PIOPERFJOB pJob)
     377{
     378    uint64_t offNext = 0;
     379
     380    switch (pJob->enmTest)
     381    {
     382        case IOPERFTEST_FIRST_WRITE:
     383        case IOPERFTEST_SEQ_WRITE:
     384        case IOPERFTEST_SEQ_READ:
     385            offNext = pJob->Tst.offNextSeq;
     386            pJob->Tst.offNextSeq += pJob->cbIoBlock;
     387            break;
     388
     389        case IOPERFTEST_REV_WRITE:
     390        case IOPERFTEST_REV_READ:
     391        case IOPERFTEST_RND_WRITE:
     392        case IOPERFTEST_RND_READ:
     393        case IOPERFTEST_SEQ_READWRITE:
     394        case IOPERFTEST_RND_READWRITE:
     395            AssertMsgFailed(("Not implemented!\n"));
     396            break;
     397        default:
     398            AssertMsgFailed(("Invalid/unknown test selected: %d\n", pJob->enmTest));
     399            break;
     400    }
     401
     402    return offNext;
     403}
     404
     405
     406/**
     407 * Returns a pointer to the write buffer with random data for the given offset which
     408 * is predictable for data verification.
     409 *
     410 * @returns Pointer to I/O block sized data buffer with random data.
     411 * @param   pJob                The job data for the current worker.
     412 * @param   off                 The offset to get the buffer for.
     413 */
     414static void *ioPerfJobTestGetWriteBufForOffset(PIOPERFJOB pJob, uint64_t off)
     415{
     416    /*
     417     * Dividing the file into 512 byte blocks so buffer pointers are at least
     418     * 512 byte aligned to work with async I/O on some platforms (Linux and O_DIRECT for example).
     419     */
     420    uint64_t uBlock = off / 512;
     421    uint32_t idxBuf = uBlock % pJob->cRandWriteBlocks512B;
     422    return pJob->pbRandWrite + idxBuf * 512;
     423}
     424
     425
     426/**
     427 * Initialize the given request for submission.
     428 *
     429 * @returns nothing.
     430 * @param   pJob                The job data for the current worker.
     431 * @param   pIoReq              The request to initialize.
     432 */
     433static void ioPerfJobTestReqInit(PIOPERFJOB pJob, PIOPERFREQ pIoReq)
     434{
     435    pIoReq->enmOp   = ioPerfJobTestGetIoQOp(pJob);
     436    pIoReq->offXfer = ioPerfJobTestGetOffsetNext(pJob);
     437    pIoReq->cbXfer  = pJob->cbIoBlock;
     438    if (pIoReq->enmOp == RTIOQUEUEOP_READ)
     439        pIoReq->pvXfer = pIoReq->pvXferRead;
     440    else if (pIoReq->enmOp == RTIOQUEUEOP_WRITE)
     441        pIoReq->pvXfer = ioPerfJobTestGetWriteBufForOffset(pJob, pIoReq->offXfer);
     442    else /* Flush */
     443        pIoReq->pvXfer = NULL;
     444
     445    pIoReq->tsStart = RTTimeNanoTS();
     446}
     447
     448
     449/**
     450 * Initializes the test state for the current test.
     451 *
     452 * @returns IPRT status code.
     453 * @param   pJob                The job data for the current worker.
     454 */
     455static int ioPerfJobTestInit(PIOPERFJOB pJob)
     456{
     457    switch (pJob->enmTest)
     458    {
     459        case IOPERFTEST_FIRST_WRITE:
     460        case IOPERFTEST_SEQ_WRITE:
     461        case IOPERFTEST_SEQ_READ:
     462            pJob->Tst.offNextSeq = 0;
     463            break;
     464
     465        case IOPERFTEST_REV_WRITE:
     466        case IOPERFTEST_REV_READ:
     467        case IOPERFTEST_RND_WRITE:
     468        case IOPERFTEST_RND_READ:
     469        case IOPERFTEST_SEQ_READWRITE:
     470        case IOPERFTEST_RND_READWRITE:
     471            AssertMsgFailed(("Not implemented!\n"));
     472            break;
     473        default:
     474            AssertMsgFailed(("Invalid/unknown test selected: %d\n", pJob->enmTest));
     475            break;
     476    }
     477
     478    return VINF_SUCCESS;
     479}
     480
     481
     482/**
     483 * Frees allocated resources specific for the current test.
     484 *
     485 * @returns nothing.
     486 * @param   pJob                The job data for the current worker.
     487 */
     488static void ioPerfJobTestFinish(PIOPERFJOB pJob)
     489{
     490    switch (pJob->enmTest)
     491    {
     492        case IOPERFTEST_FIRST_WRITE:
     493        case IOPERFTEST_SEQ_WRITE:
     494        case IOPERFTEST_SEQ_READ:
     495            break; /* Nothing to do. */
     496
     497        case IOPERFTEST_REV_WRITE:
     498        case IOPERFTEST_REV_READ:
     499        case IOPERFTEST_RND_WRITE:
     500        case IOPERFTEST_RND_READ:
     501        case IOPERFTEST_SEQ_READWRITE:
     502        case IOPERFTEST_RND_READWRITE:
     503            AssertMsgFailed(("Not implemented!\n"));
     504            break;
     505        default:
     506            AssertMsgFailed(("Invalid/unknown test selected: %d\n", pJob->enmTest));
     507            break;
     508    }
     509}
     510
     511
     512/**
     513 * Returns whether the current test is done with submitting new requests (reached test set size).
     514 *
     515 * @returns True when the test has submitted all required requests, false if there are still requests required
     516 */
     517static bool ioPerfJobTestIsDone(PIOPERFJOB pJob)
     518{
     519    switch (pJob->enmTest)
     520    {
     521        case IOPERFTEST_FIRST_WRITE:
     522        case IOPERFTEST_SEQ_WRITE:
     523        case IOPERFTEST_SEQ_READ:
     524            return pJob->Tst.offNextSeq == pJob->cbTestSet;
     525
     526        case IOPERFTEST_REV_WRITE:
     527        case IOPERFTEST_REV_READ:
     528        case IOPERFTEST_RND_WRITE:
     529        case IOPERFTEST_RND_READ:
     530        case IOPERFTEST_SEQ_READWRITE:
     531        case IOPERFTEST_RND_READWRITE:
     532            AssertMsgFailed(("Not implemented!\n"));
     533            break;
     534        default:
     535            AssertMsgFailed(("Invalid/unknown test selected: %d\n", pJob->enmTest));
     536            break;
     537    }
     538
     539    return true;
     540}
     541
     542
     543/**
     544 * The test I/O loop pumping I/O.
     545 *
     546 * @returns IPRT status code.
     547 * @param   pJob                The job data for the current worker.
     548 */
     549static int ioPerfJobTestIoLoop(PIOPERFJOB pJob)
     550{
     551    int rc = ioPerfJobTestInit(pJob);
     552    if (RT_SUCCESS(rc))
     553    {
     554        /* Allocate the completion event array. */
     555        uint32_t cReqsQueued = 0;
     556        PRTIOQUEUECEVT paIoQCEvt = (PRTIOQUEUECEVT)RTMemAllocZ(pJob->cReqsMax * sizeof(RTIOQUEUECEVT));
     557        if (RT_LIKELY(paIoQCEvt))
     558        {
     559            /* Queue requests up to the maximum. */
     560            while (   (cReqsQueued < pJob->cReqsMax)
     561                   && !ioPerfJobTestIsDone(pJob)
     562                   && RT_SUCCESS(rc))
     563            {
     564                PIOPERFREQ pReq = &pJob->paIoReqs[cReqsQueued];
     565                ioPerfJobTestReqInit(pJob, pReq);
     566                rc = RTIoQueueRequestPrepare(pJob->hIoQueue, &pJob->Hnd, pReq->enmOp,
     567                                             pReq->offXfer, pReq->pvXfer, pReq->cbXfer, 0 /*fReqFlags*/,
     568                                             pReq);
     569                cReqsQueued++;
     570            }
     571
     572            /* Commit the prepared requests. */
     573            if (   RT_SUCCESS(rc)
     574                && cReqsQueued)
     575                rc = RTIoQueueCommit(pJob->hIoQueue);
     576
     577            /* Enter wait loop and process completed requests. */
     578            while (   RT_SUCCESS(rc)
     579                   && cReqsQueued)
     580            {
     581                uint32_t cCEvtCompleted = 0;
     582
     583                rc = RTIoQueueEvtWait(pJob->hIoQueue, paIoQCEvt, pJob->cReqsMax, 1 /*cMinWait*/,
     584                                      &cCEvtCompleted, 0 /*fFlags*/);
     585                if (RT_SUCCESS(rc))
     586                {
     587                    uint32_t cReqsThisQueued = 0;
     588
     589                    /* Process any completed event and continue to fill the queue as long as there is stuff to do. */
     590                    for (uint32_t i = 0; i < cCEvtCompleted; i++)
     591                    {
     592                        PIOPERFREQ pReq = (PIOPERFREQ)paIoQCEvt[i].pvUser;
     593
     594                        if (RT_SUCCESS(paIoQCEvt[i].rcReq))
     595                        {
     596                            Assert(paIoQCEvt[i].cbXfered == pReq->cbXfer);
     597
     598                            /** @todo Statistics collection. */
     599                            if (!ioPerfJobTestIsDone(pJob))
     600                            {
     601                                ioPerfJobTestReqInit(pJob, pReq);
     602                                rc = RTIoQueueRequestPrepare(pJob->hIoQueue, &pJob->Hnd, pReq->enmOp,
     603                                                             pReq->offXfer, pReq->pvXfer, pReq->cbXfer, 0 /*fReqFlags*/,
     604                                                             pReq);
     605                                cReqsThisQueued++;
     606                            }
     607                            else
     608                                cReqsQueued--;
     609                        }
     610                    }
     611
     612                    if (   cReqsThisQueued
     613                        && RT_SUCCESS(rc))
     614                        rc = RTIoQueueCommit(pJob->hIoQueue);
     615                }
     616            }
     617
     618            RTMemFree(paIoQCEvt);
     619        }
     620
     621        ioPerfJobTestFinish(pJob);
     622    }
     623
     624    return rc;
    293625}
    294626
     
    304636    if (pJob->pMaster)
    305637    {
    306         /* Enter the rendevouzs semaphore. */
     638        /* Enter the rendezvous semaphore. */
    307639        int rc = VINF_SUCCESS;
    308640
     
    312644    /* Single threaded run, collect the results from our current test and select the next test. */
    313645    /** @todo Results and statistics collection. */
    314     pJob->enmTest = ioPerfTestSelectNext();
     646    pJob->enmTest = ioPerfJobTestSelectNext();
    315647    return VINF_SUCCESS;
    316 }
    317 
    318 
    319 /**
    320  * Sequential read test.
    321  *
    322  * @returns IPRT status code.
    323  * @param   pJob                The job data for the current worker.
    324  */
    325 static int ioPerfTestSeqRead(PIOPERFJOB pJob)
    326 {
    327     RT_NOREF(pJob);
    328     return VERR_NOT_IMPLEMENTED;
    329648}
    330649
     
    348667            break;
    349668
    350         switch (pJob->enmTest)
    351         {
    352             case IOPERFTEST_FIRST_WRITE:
    353                 break;
    354             case IOPERFTEST_SEQ_READ:
    355                 rc = ioPerfTestSeqRead(pJob);
    356                 break;
    357             case IOPERFTEST_SEQ_WRITE:
    358                 break;
    359             case IOPERFTEST_RND_READ:
    360                 break;
    361             case IOPERFTEST_RND_WRITE:
    362                 break;
    363             case IOPERFTEST_REV_READ:
    364                 break;
    365             case IOPERFTEST_REV_WRITE:
    366                 break;
    367             case IOPERFTEST_SEQ_READWRITE:
    368                 break;
    369             case IOPERFTEST_RND_READWRITE:
    370                 break;
    371             case IOPERFTEST_SHUTDOWN:
    372                 fShutdown = true;
    373                 break;
    374             default:
    375                 AssertMsgFailed(("Invalid job: %d\n", pJob->enmTest));
    376         }
     669        rc = ioPerfJobTestIoLoop(pJob);
    377670    } while (   RT_SUCCESS(rc)
    378671             && !fShutdown);
     
    391684    PIOPERFJOB pJob = (PIOPERFJOB)pvUser;
    392685    return ioPerfJobWorkLoop(pJob);
     686}
     687
     688
     689/**
     690 * Prepares the test set by laying out the files and filling them with data.
     691 *
     692 * @returns IPRT status code.
     693 * @param   pJob                The job to initialize.
     694 */
     695static int ioPerfJobTestSetPrep(PIOPERFJOB pJob)
     696{
     697    int rc = RTRandAdvCreateParkMiller(&pJob->hRand);
     698    if (RT_SUCCESS(rc))
     699    {
     700        rc = RTRandAdvSeed(pJob->hRand, RTTimeNanoTS());
     701        if (RT_SUCCESS(rc))
     702        {
     703            /*
     704             * Create a random data buffer for writes, we'll use multiple of the I/O block size to
     705             * be able to seek in the buffer quite a bit to make the file content as random as possible
     706             * to avoid mechanisms like compression or deduplication for now which can influence storage
     707             * benchmarking unpredictably.
     708             */
     709            pJob->cRandWriteBlocks512B = ((IOPERF_RAND_DATA_BUF_FACTOR - 1) * pJob->cbIoBlock) / 512;
     710            pJob->pbRandWrite = (uint8_t *)RTMemPageAllocZ(IOPERF_RAND_DATA_BUF_FACTOR * pJob->cbIoBlock);
     711            if (RT_LIKELY(pJob->pbRandWrite))
     712            {
     713                RTRandAdvBytes(pJob->hRand, pJob->pbRandWrite, IOPERF_RAND_DATA_BUF_FACTOR * pJob->cbIoBlock);
     714
     715                /* Write the content here if the first write test is disabled. */
     716                if (g_aenmTests[IOPERFTEST_FIRST_WRITE] == IOPERFTEST_DISABLED)
     717                {
     718                    for (uint64_t off = 0; off < pJob->cbTestSet && RT_SUCCESS(rc); off += pJob->cbIoBlock)
     719                    {
     720                        void *pvWrite = ioPerfJobTestGetWriteBufForOffset(pJob, off);
     721                        rc = RTFileWriteAt(pJob->Hnd.u.hFile, off, pvWrite, pJob->cbIoBlock, NULL);
     722                    }
     723                }
     724            }
     725        }
     726        RTRandAdvDestroy(pJob->hRand);
     727    }
     728
     729    return rc;
    393730}
    394731
     
    413750                         uint64_t cbTestSet, size_t cbIoBlock, uint32_t cReqsMax)
    414751{
    415     pJob->pMaster     = pMaster;
    416     pJob->idJob       = idJob;
    417     pJob->enmTest     = IOPERFTEST_INVALID;
    418     pJob->hThread     = NIL_RTTHREAD;
    419     pJob->Hnd.enmType = RTHANDLETYPE_FILE;
    420     pJob->cbTestSet   = cbTestSet;
    421     pJob->cbIoBlock   = cbIoBlock;
    422     pJob->cReqsMax    = cReqsMax;
    423 
    424     /* Create the file. */
     752    pJob->pMaster        = pMaster;
     753    pJob->idJob          = idJob;
     754    pJob->enmTest        = IOPERFTEST_INVALID;
     755    pJob->hThread        = NIL_RTTHREAD;
     756    pJob->Hnd.enmType    = RTHANDLETYPE_FILE;
     757    pJob->cbTestSet      = cbTestSet;
     758    pJob->cbIoBlock      = cbIoBlock;
     759    pJob->cReqsMax       = cReqsMax;
     760    pJob->cbIoReqReadBuf = cReqsMax * cbIoBlock;
     761
    425762    int rc = VINF_SUCCESS;
    426     pJob->pszFilename = RTStrAPrintf2("%sioperf-%u.file", pszTestDir, idJob);
    427     if (RT_LIKELY(pJob->pszFilename))
    428     {
    429         rc = RTFileOpen(&pJob->Hnd.u.hFile, pJob->pszFilename, RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE | RTFILE_O_READWRITE);
    430         if (RT_SUCCESS(rc))
     763    pJob->paIoReqs = (PIOPERFREQ)RTMemAllocZ(cReqsMax * sizeof(IOPERFREQ));
     764    if (RT_LIKELY(pJob->paIoReqs))
     765    {
     766        pJob->pvIoReqReadBuf = RTMemPageAlloc(pJob->cbIoReqReadBuf);
     767        if (RT_LIKELY(pJob->pvIoReqReadBuf))
    431768        {
    432             switch (enmPrepMethod)
     769            uint8_t *pbReadBuf = (uint8_t *)pJob->pvIoReqReadBuf;
     770
     771            for (uint32_t i = 0; i < cReqsMax; i++)
    433772            {
    434                 case IOPERFTESTSETPREP_JUST_CREATE:
    435                     break;
    436                 case IOPERFTESTSETPREP_SET_SZ:
    437                     rc = RTFileSetSize(pJob->Hnd.u.hFile, pJob->cbTestSet);
    438                     break;
    439                 case IOPERFTESTSETPREP_SET_ALLOC_SZ:
    440                     rc = RTFileSetAllocationSize(pJob->Hnd.u.hFile, pJob->cbTestSet, RTFILE_ALLOC_SIZE_F_DEFAULT);
    441                     break;
    442                 default:
    443                     AssertMsgFailed(("Invalid file preparation method: %d\n", enmPrepMethod));
     773                pJob->paIoReqs[i].pvXferRead = pbReadBuf;
     774                pJob->paIoReqs[i].cbXferRead = cbIoBlock;
     775                pbReadBuf += cbIoBlock;
    444776            }
    445777
    446             if (RT_SUCCESS(rc))
     778            /* Create the file. */
     779            pJob->pszFilename = RTStrAPrintf2("%sioperf-%u.file", pszTestDir, idJob);
     780            if (RT_LIKELY(pJob->pszFilename))
    447781            {
    448                 /* Create I/O queue. */
    449                 PCRTIOQUEUEPROVVTABLE pIoQProv = NULL;
    450                 if (pszIoEngine)
    451                     pIoQProv = RTIoQueueProviderGetBestForHndType(RTHANDLETYPE_FILE);
    452                 else
    453                     pIoQProv = RTIoQueueProviderGetById(pszIoEngine);
    454 
    455                 if (RT_LIKELY(pIoQProv))
     782                rc = RTFileOpen(&pJob->Hnd.u.hFile, pJob->pszFilename, RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE | RTFILE_O_READWRITE);
     783                if (RT_SUCCESS(rc))
    456784                {
    457                     rc = RTIoQueueCreate(&pJob->hIoQueue, pIoQProv, 0 /*fFlags*/, cReqsMax, cReqsMax);
     785                    switch (enmPrepMethod)
     786                    {
     787                        case IOPERFTESTSETPREP_JUST_CREATE:
     788                            break;
     789                        case IOPERFTESTSETPREP_SET_SZ:
     790                            rc = RTFileSetSize(pJob->Hnd.u.hFile, pJob->cbTestSet);
     791                            break;
     792                        case IOPERFTESTSETPREP_SET_ALLOC_SZ:
     793                            rc = RTFileSetAllocationSize(pJob->Hnd.u.hFile, pJob->cbTestSet, RTFILE_ALLOC_SIZE_F_DEFAULT);
     794                            break;
     795                        default:
     796                            AssertMsgFailed(("Invalid file preparation method: %d\n", enmPrepMethod));
     797                    }
     798
    458799                    if (RT_SUCCESS(rc))
    459800                    {
    460                         /* Spin up the worker thread. */
    461                         if (pMaster)
    462                             rc = RTThreadCreateF(&pJob->hThread, ioPerfJobThread, pJob, 0,
    463                                                  RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "ioperf-%u", idJob);
    464 
     801                        rc = ioPerfJobTestSetPrep(pJob);
    465802                        if (RT_SUCCESS(rc))
    466                             return VINF_SUCCESS;
     803                        {
     804                            /* Create I/O queue. */
     805                            PCRTIOQUEUEPROVVTABLE pIoQProv = NULL;
     806                            if (!pszIoEngine)
     807                                pIoQProv = RTIoQueueProviderGetBestForHndType(RTHANDLETYPE_FILE);
     808                            else
     809                                pIoQProv = RTIoQueueProviderGetById(pszIoEngine);
     810
     811                            if (RT_LIKELY(pIoQProv))
     812                            {
     813                                rc = RTIoQueueCreate(&pJob->hIoQueue, pIoQProv, 0 /*fFlags*/, cReqsMax, cReqsMax);
     814                                if (RT_SUCCESS(rc))
     815                                {
     816                                    rc = RTIoQueueHandleRegister(pJob->hIoQueue, &pJob->Hnd);
     817                                    if (RT_SUCCESS(rc))
     818                                    {
     819                                        /* Spin up the worker thread. */
     820                                        if (pMaster)
     821                                            rc = RTThreadCreateF(&pJob->hThread, ioPerfJobThread, pJob, 0,
     822                                                                 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "ioperf-%u", idJob);
     823
     824                                        if (RT_SUCCESS(rc))
     825                                            return VINF_SUCCESS;
     826                                    }
     827                                }
     828                            }
     829                            else
     830                                rc = VERR_NOT_SUPPORTED;
     831                        }
     832
     833                        RTRandAdvDestroy(pJob->hRand);
    467834                    }
     835
     836                    RTFileClose(pJob->Hnd.u.hFile);
     837                    RTFileDelete(pJob->pszFilename);
    468838                }
    469                 else
    470                     rc = VERR_NOT_SUPPORTED;
     839
     840                RTStrFree(pJob->pszFilename);
    471841            }
    472842
    473             RTFileClose(pJob->Hnd.u.hFile);
    474             RTFileDelete(pJob->pszFilename);
     843            RTMemPageFree(pJob->pvIoReqReadBuf, pJob->cbIoReqReadBuf);
    475844        }
    476 
    477         RTStrFree(pJob->pszFilename);
    478     }
    479     else
    480         rc = VERR_NO_STR_MEMORY;
     845        else
     846            rc = VERR_NO_STR_MEMORY;
     847    }
    481848
    482849    return rc;
     
    492859static int ioPerfJobTeardown(PIOPERFJOB pJob)
    493860{
    494     int rc = RTThreadWait(pJob->hThread, RT_INDEFINITE_WAIT, NULL); AssertRC(rc); RT_NOREF(rc);
    495 
     861    if (pJob->pMaster)
     862    {
     863        int rc = RTThreadWait(pJob->hThread, RT_INDEFINITE_WAIT, NULL);
     864        AssertRC(rc); RT_NOREF(rc);
     865    }
     866
     867    RTIoQueueHandleDeregister(pJob->hIoQueue, &pJob->Hnd);
    496868    RTIoQueueDestroy(pJob->hIoQueue);
     869    RTRandAdvDestroy(pJob->hRand);
     870    RTMemPageFree(pJob->pbRandWrite, IOPERF_RAND_DATA_BUF_FACTOR * pJob->cbIoBlock);
    497871    RTFileClose(pJob->Hnd.u.hFile);
    498872    RTFileDelete(pJob->pszFilename);
    499873    RTStrFree(pJob->pszFilename);
     874    RTMemPageFree(pJob->pvIoReqReadBuf, pJob->cbIoReqReadBuf);
     875    RTMemFree(pJob->paIoReqs);
    500876    return VINF_SUCCESS;
    501877}
     
    512888
    513889    int rc = ioPerfJobInit(&Job, NULL, 0, g_pszIoEngine,
    514                            g_szDir, IOPERFTESTSETPREP_SET_ALLOC_SZ,
     890                           g_szDir, IOPERFTESTSETPREP_SET_SZ,
    515891                           g_cbTestSet, g_cbIoBlock, g_cReqsMax);
    516892    if (RT_SUCCESS(rc))
     
    558934            case 'd':                           pszHelp = "The directory to use for testing.            default: CWD/fstestdir"; break;
    559935            case 'r':                           pszHelp = "Don't abspath test dir (good for deep dirs). default: disabled"; break;
    560             case 'e':                           pszHelp = "Enables all tests.                           default: -e"; break;
    561             case 'z':                           pszHelp = "Disables all tests.                          default: -e"; break;
    562936            case 'v':                           pszHelp = "More verbose execution."; break;
    563937            case 'q':                           pszHelp = "Quiet execution."; break;
     
    620994                break;
    621995
     996            case 'i':
     997                g_pszIoEngine = ValueUnion.psz;
     998                break;
     999
     1000            case 's':
     1001                g_cbTestSet = ValueUnion.u64;
     1002                break;
     1003
     1004            case 'b':
     1005                g_cbIoBlock = ValueUnion.u32;
     1006                break;
     1007
     1008            case 'm':
     1009                g_cReqsMax = ValueUnion.u32;
     1010                break;
     1011
    6221012            case 'q':
    6231013                g_uVerbosity = 0;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette