VirtualBox

Changeset 76897 in vbox for trunk/src/VBox/ValidationKit


Ignore:
Timestamp:
Jan 19, 2019 6:56:27 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
128265
Message:

FsPerf: Updates. bugref:9172

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/utils/fs/FsPerf.cpp

    r76889 r76897  
    6262    do { \
    6363        /* Estimate how many iterations we need to fill up the given timeslot: */ \
    64         uint64_t const nsStartEstimation = RTTimeNanoTS(); \
    65         for (uint32_t iIteration = 0; iIteration < 64; iIteration++) \
     64        fsPerfYield(); \
     65        uint64_t nsStart = RTTimeNanoTS(); \
     66        uint64_t ns; \
     67        do \
     68            ns = RTTimeNanoTS(); \
     69        while (ns == nsStart); \
     70        nsStart = ns; \
     71        \
     72        uint64_t iIteration = 0; \
     73        do \
    6674        { \
    6775            RTTESTI_CHECK_RC(a_fnCall, VINF_SUCCESS); \
    68         } \
    69         uint64_t cNs = RTTimeNanoTS() - nsStartEstimation; \
    70         cNs /= 64; \
    71         uint32_t const cIterations = (((a_cNsTarget) / cNs) + 255) / 256 * 256; \
     76            iIteration++; \
     77            ns = RTTimeNanoTS() - nsStart; \
     78        } while (ns < RT_NS_10MS || (iIteration & 1)); \
     79        ns /= iIteration; \
     80        if (ns > g_nsPerNanoTSCall + 32) \
     81            ns -= g_nsPerNanoTSCall; \
     82        \
     83        uint64_t cIterations = (a_cNsTarget) / ns; \
     84        if (cIterations <= 1) \
     85            cIterations = 2; \
     86        else if (cIterations & 1) \
     87            cIterations++; \
    7288        \
    7389        /* Do the actual profiling: */ \
    7490        fsPerfYield(); \
    75         uint64_t const nsStart = RTTimeNanoTS(); \
    76         for (uint32_t iIteration = 0; iIteration < cIterations; iIteration++) \
    77         { \
    78             a_fnCall; \
    79         } \
    80         uint64_t const cNsElapsed = RTTimeNanoTS() - nsStart; \
    81         RTTestIValueF(cNsElapsed / cIterations, RTTESTUNIT_NS_PER_OCCURRENCE, a_szDesc); \
     91        iIteration = 0; \
     92        nsStart = RTTimeNanoTS(); \
     93        for (; iIteration < cIterations; iIteration++) \
     94            RTTESTI_CHECK_RC(a_fnCall, VINF_SUCCESS); \
     95        ns = RTTimeNanoTS() - nsStart; \
     96        RTTestIValueF(ns / cIterations, RTTESTUNIT_NS_PER_OCCURRENCE, a_szDesc); \
     97        if (g_fShowDuration) \
     98            RTTestIValueF(ns, RTTESTUNIT_NS, "%s duration", a_szDesc); \
    8299    } while (0)
    83100
     
    94111        \
    95112        /* Estimate how many iterations we need to fill up the given timeslot: */ \
    96         uint64_t const nsStartEstimation = RTTimeNanoTS(); \
     113        fsPerfYield(); \
     114        uint64_t nsStart = RTTimeNanoTS(); \
     115        uint64_t ns; \
     116        do \
     117            ns = RTTimeNanoTS(); \
     118        while (ns == nsStart); \
     119        nsStart = ns; \
     120        \
    97121        PFSPERFNAMEENTRY pCur; \
    98         for (uint32_t iIteration = 0; iIteration < (a_cEstimationIterations); iIteration++) \
     122        uint64_t iIteration = 0; \
     123        do \
    99124        { \
    100125            RTListForEach(&g_ManyTreeHead, pCur, FSPERFNAMEENTRY, Entry) \
     
    107132                } \
    108133            } \
    109         } \
    110         uint64_t cNs = RTTimeNanoTS() - nsStartEstimation; \
    111         uint32_t const cIterations = RT_ALIGN_32(((a_cNsTarget) + cNs - 1) / (cNs / 2), 2); \
     134            iIteration++; \
     135            ns = RTTimeNanoTS() - nsStart; \
     136        } while (ns < RT_NS_10MS || (iIteration & 1)); \
     137        ns /= iIteration; \
     138        if (ns > g_nsPerNanoTSCall + 32) \
     139            ns -= g_nsPerNanoTSCall; \
     140        \
     141        uint32_t cIterations = (a_cNsTarget) / ns; \
     142        if (cIterations <= 1) \
     143            cIterations = 2; \
     144        else if (cIterations & 1) \
     145            cIterations++; \
     146        \
    112147        /* Do the actual profiling: */ \
    113148        fsPerfYield(); \
    114         uint32_t       cCalls = 0; \
    115         uint64_t const nsStart = RTTimeNanoTS(); \
    116         for (uint32_t iIteration = 0; iIteration < cIterations; iIteration++) \
     149        uint32_t cCalls = 0; \
     150        nsStart = RTTimeNanoTS(); \
     151        for (iIteration = 0; iIteration < cIterations; iIteration++) \
    117152        { \
    118153            RTListForEach(&g_ManyTreeHead, pCur, FSPERFNAMEENTRY, Entry) \
     
    127162            } \
    128163        } \
    129         uint64_t const cNsElapsed = RTTimeNanoTS() - nsStart; \
    130         RTTestIValueF(cNsElapsed / cCalls, RTTESTUNIT_NS_PER_OCCURRENCE, a_szDesc); \
     164        ns = RTTimeNanoTS() - nsStart; \
     165        RTTestIValueF(ns / cCalls, RTTESTUNIT_NS_PER_OCCURRENCE, a_szDesc); \
     166        if (g_fShowDuration) \
     167            RTTestIValueF(ns, RTTESTUNIT_NS, "%s duration", a_szDesc); \
    131168    } while (0)
    132169
     
    273310 * This is used for adjusting loop count estimates.  */
    274311static uint64_t     g_nsPerNanoTSCall = 1;
     312/** Whether or not to display the duration of each profile run.
     313 * This is chiefly for verify the estimate phase.  */
     314static bool         g_fShowDuration = true;
    275315/** Verbosity level. */
    276316static uint32_t     g_uVerbosity = 0;
     
    298338
    299339/** The length of each test run. */
    300 static uint64_t     g_nsTestRun  = RT_NS_1SEC_64 * 10;
     340static uint64_t     g_nsTestRun                 = RT_NS_1SEC_64 * 10;
    301341
    302342/** For the 'manyfiles' subdir.  */
    303 static uint32_t     g_cManyFiles = 10000;
     343static uint32_t     g_cManyFiles                = 10000;
    304344
    305345/** Number of files in the 'manytree' directory tree.  */
    306 static uint32_t     g_cManyTreeFiles         = 640 + 16*640 /*10880*/;
     346static uint32_t     g_cManyTreeFiles            = 640 + 16*640 /*10880*/;
    307347/** Number of files per directory in the 'manytree' construct. */
    308 static uint32_t     g_cManyTreeFilesPerDir   = 640;
     348static uint32_t     g_cManyTreeFilesPerDir      = 640;
    309349/* Number of subdirs per directory in the 'manytree' construct. */
    310 static uint32_t     g_cManyTreeSubdirsPerDir = 16;
     350static uint32_t     g_cManyTreeSubdirsPerDir    = 16;
    311351/** The depth of the 'manytree' directory tree.  */
    312 static uint32_t     g_cManyTreeDepth          = 1;
     352static uint32_t     g_cManyTreeDepth            = 1;
    313353/** List of directories in the many tree, creation order. */
    314354static RTLISTANCHOR g_ManyTreeHead;
    315355
    316356/** Number of configured I/O block sizes. */
    317 static uint32_t     g_cIoBlocks       = 8;
     357static uint32_t     g_cIoBlocks                 = 8;
    318358/** Configured I/O block sizes. */
    319 static uint32_t     g_acbIoBlocks[16] = { 1, 512, 4096, 16384, 65536, _1M, _32M, _128M };
     359static uint32_t     g_acbIoBlocks[16]           = { 1, 512, 4096, 16384, 65536, _1M, _32M, _128M };
    320360/** The desired size of the test file we use for I/O. */
    321 static uint64_t     g_cbIoFile        = _512M;
     361static uint64_t     g_cbIoFile                  = _512M;
    322362
    323363/** The length of g_szDir. */
     
    423463
    424464/**
     465 * Prepares the test area.
     466 * @returns VBox status code.
     467 */
     468static int fsPrepTestArea(void)
     469{
     470    /* The empty subdir and associated globals: */
     471    static char s_szEmpty[] = "empty";
     472    memcpy(g_szEmptyDir, g_szDir, g_cchDir);
     473    memcpy(&g_szEmptyDir[g_cchDir], s_szEmpty, sizeof(s_szEmpty));
     474    g_cchEmptyDir = g_cchDir + sizeof(s_szEmpty) - 1;
     475    RTTESTI_CHECK_RC_RET(RTDirCreate(g_szEmptyDir, 0755, 0), VINF_SUCCESS, rcCheck);
     476    g_szEmptyDir[g_cchEmptyDir++] = RTPATH_SLASH;
     477    g_szEmptyDir[g_cchEmptyDir]   = '\0';
     478    RTTestIPrintf(RTTESTLVL_ALWAYS, "Empty dir: %s\n", g_szEmptyDir);
     479
     480    /* Deep directory: */
     481    memcpy(g_szDeepDir, g_szDir, g_cchDir);
     482    g_cchDeepDir = g_cchDir;
     483    do
     484    {
     485        static char const s_szSub[] = "d" RTPATH_SLASH_STR;
     486        memcpy(&g_szDeepDir[g_cchDeepDir], s_szSub, sizeof(s_szSub));
     487        g_cchDeepDir += sizeof(s_szSub) - 1;
     488        RTTESTI_CHECK_RC_RET( RTDirCreate(g_szDeepDir, 0755, 0), VINF_SUCCESS, rcCheck);
     489    } while (g_cchDeepDir < 176);
     490    RTTestIPrintf(RTTESTLVL_ALWAYS, "Deep  dir: %s\n", g_szDeepDir);
     491
     492    /* Create known file in both deep and shallow dirs: */
     493    RTFILE hKnownFile;
     494    RTTESTI_CHECK_RC_RET(RTFileOpen(&hKnownFile, InDir(RT_STR_TUPLE("known-file")),
     495                                    RTFILE_O_CREATE | RTFILE_O_DENY_NONE | RTFILE_O_WRITE),
     496                         VINF_SUCCESS, rcCheck);
     497    RTTESTI_CHECK_RC_RET(RTFileClose(hKnownFile), VINF_SUCCESS, rcCheck);
     498
     499    RTTESTI_CHECK_RC_RET(RTFileOpen(&hKnownFile, InDeepDir(RT_STR_TUPLE("known-file")),
     500                                    RTFILE_O_CREATE | RTFILE_O_DENY_NONE | RTFILE_O_WRITE),
     501                         VINF_SUCCESS, rcCheck);
     502    RTTESTI_CHECK_RC_RET(RTFileClose(hKnownFile), VINF_SUCCESS, rcCheck);
     503
     504    return VINF_SUCCESS;
     505}
     506
     507
     508/**
    425509 * Create a name list entry.
    426510 * @returns Pointer to the entry, NULL if out of memory.
     
    460544    return VINF_SUCCESS;
    461545}
    462 
    463 
    464 DECL_FORCE_INLINE(int) fsPerfOpenExistingOnceReadonly(const char *pszFile)
    465 {
    466     RTFILE hFile;
    467     RTTESTI_CHECK_RC_RET(RTFileOpen(&hFile, pszFile, RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READ), VINF_SUCCESS, rcCheck);
    468     RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS);
    469     return VINF_SUCCESS;
    470 }
    471 
    472 
    473 DECL_FORCE_INLINE(int) fsPerfOpenExistingOnceWriteonly(const char *pszFile)
    474 {
    475     RTFILE hFile;
    476     RTTESTI_CHECK_RC_RET(RTFileOpen(&hFile, pszFile, RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_WRITE), VINF_SUCCESS, rcCheck);
    477     RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS);
    478     return VINF_SUCCESS;
    479 }
    480 
    481546
    482547
     
    545610
    546611
     612DECL_FORCE_INLINE(int) fsPerfOpenExistingOnceReadonly(const char *pszFile)
     613{
     614    RTFILE hFile;
     615    RTTESTI_CHECK_RC_RET(RTFileOpen(&hFile, pszFile, RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READ), VINF_SUCCESS, rcCheck);
     616    RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS);
     617    return VINF_SUCCESS;
     618}
     619
     620
     621DECL_FORCE_INLINE(int) fsPerfOpenExistingOnceWriteonly(const char *pszFile)
     622{
     623    RTFILE hFile;
     624    RTTESTI_CHECK_RC_RET(RTFileOpen(&hFile, pszFile, RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_WRITE), VINF_SUCCESS, rcCheck);
     625    RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS);
     626    return VINF_SUCCESS;
     627}
     628
     629
    547630void fsPerfOpen(void)
    548631{
     
    555638    RTTESTI_CHECK_RC(RTFileOpen(&hFile, InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file")),
    556639                                RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READ), FSPERF_VERR_PATH_NOT_FOUND);
     640    RTTESTI_CHECK_RC(RTFileOpen(&hFile, InDir(RT_STR_TUPLE("known-file" RTPATH_SLASH_STR "no-such-file")),
     641                                RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READ), VERR_PATH_NOT_FOUND);
    557642
    558643    /*
     
    660745    RTTESTI_CHECK_RC(RTPathQueryInfoEx(InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file")),
    661746                                       &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK), FSPERF_VERR_PATH_NOT_FOUND);
     747    RTTESTI_CHECK_RC(RTPathQueryInfoEx(InDir(RT_STR_TUPLE("known-file" RTPATH_SLASH_STR "no-such-file")),
     748                                       &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK), VERR_PATH_NOT_FOUND);
    662749
    663750    /* Shallow: */
     
    701788    RTTESTI_CHECK_RC(RTPathSetMode(InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file")), 0665),
    702789                     FSPERF_VERR_PATH_NOT_FOUND);
     790    RTTESTI_CHECK_RC(RTPathSetMode(InDir(RT_STR_TUPLE("known-file" RTPATH_SLASH_STR "no-such-file")), 0665), VERR_PATH_NOT_FOUND);
    703791
    704792    /* Shallow: */
     
    746834                                      NULL, &Time1, NULL, NULL, RTPATH_F_ON_LINK),
    747835                     FSPERF_VERR_PATH_NOT_FOUND);
     836    RTTESTI_CHECK_RC(RTPathSetTimesEx(InDir(RT_STR_TUPLE("known-file" RTPATH_SLASH_STR "no-such-file")),
     837                                      NULL, &Time1, NULL, NULL, RTPATH_F_ON_LINK),
     838                     VERR_PATH_NOT_FOUND);
    748839
    749840    /* Shallow: */
     
    813904    RTTESTI_CHECK_RC(RTPathRename(InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file")), szPath, 0),
    814905                     FSPERF_VERR_PATH_NOT_FOUND);
     906    strcpy(szPath, InEmptyDir(RT_STR_TUPLE("other-no-such-file")));
     907    RTTESTI_CHECK_RC(RTPathRename(InDir(RT_STR_TUPLE("known-file" RTPATH_SLASH_STR "no-such-file")), szPath, 0), VERR_PATH_NOT_FOUND);
    815908
    816909    RTFILE hFile1;
     
    881974{
    882975    RTTestISub("dir enum");
     976    RTDIR hDir;
     977
     978    /* Non-existing files. */
     979    RTTESTI_CHECK_RC(RTDirOpen(&hDir, InEmptyDir(RT_STR_TUPLE("no-such-file"))), VERR_FILE_NOT_FOUND);
     980    RTTESTI_CHECK_RC(RTDirOpen(&hDir, InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file"))), FSPERF_VERR_PATH_NOT_FOUND);
     981    RTTESTI_CHECK_RC(RTDirOpen(&hDir, InDir(RT_STR_TUPLE("known-file" RTPATH_SLASH_STR "no-such-file"))), VERR_PATH_NOT_FOUND);
    883982
    884983    /*
    885984     * The empty directory.
    886985     */
    887     RTDIR hDir;
    888986    g_szEmptyDir[g_cchEmptyDir] = '\0';
    889987    RTTESTI_CHECK_RC_RETV(RTDirOpen(&hDir, g_szEmptyDir), VINF_SUCCESS);
     
    9821080    RTTESTI_CHECK_RC(RTDirRemove(InEmptyDir(RT_STR_TUPLE("no-such-dir"))), VERR_FILE_NOT_FOUND);
    9831081    RTTESTI_CHECK_RC(RTDirRemove(InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file"))), FSPERF_VERR_PATH_NOT_FOUND);
     1082    RTTESTI_CHECK_RC(RTDirRemove(InDir(RT_STR_TUPLE("known-file" RTPATH_SLASH_STR "no-such-file"))), VERR_PATH_NOT_FOUND);
    9841083    RTTESTI_CHECK_RC(RTDirCreate(InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file")), 0755, 0), FSPERF_VERR_PATH_NOT_FOUND);
     1084    RTTESTI_CHECK_RC(RTDirCreate(InDir(RT_STR_TUPLE("known-file" RTPATH_SLASH_STR "no-such-file")), 0755, 0), VERR_PATH_NOT_FOUND);
    9851085
    9861086    /** @todo check what happens if non-final path component isn't a directory. unix
     
    9981098    RTTESTI_CHECK_RC(RTDirRemove(InDir(RT_STR_TUPLE("."))), VERR_INVALID_PARAMETER); /* EINVAL for '.' */
    9991099#endif
     1100#if defined(RT_OS_WINDOWS)
     1101    RTTESTI_CHECK_RC(RTDirRemove(InDir(RT_STR_TUPLE(".."))), VERR_SHARING_VIOLATION); /* weird */
     1102#else
    10001103    RTTESTI_CHECK_RC(RTDirRemove(InDir(RT_STR_TUPLE(".."))), VERR_DIR_NOT_EMPTY);
     1104#endif
    10011105    RTTESTI_CHECK_RC(RTDirRemove(InDir(RT_STR_TUPLE(""))), VERR_DIR_NOT_EMPTY);
    10021106
     
    10871191    RTTESTI_CHECK_RC(RTFileDelete(InEmptyDir(RT_STR_TUPLE("no-such-file"))), VERR_FILE_NOT_FOUND);
    10881192    RTTESTI_CHECK_RC(RTFileDelete(InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file"))), FSPERF_VERR_PATH_NOT_FOUND);
     1193    RTTESTI_CHECK_RC(RTFileDelete(InDir(RT_STR_TUPLE("known-file" RTPATH_SLASH_STR "no-such-file"))), VERR_PATH_NOT_FOUND);
    10891194
    10901195    /* Directories: */
     
    11431248     * We need some free space to perform this test.
    11441249     */
     1250    g_szDir[g_cchDir] = '\0';
    11451251    RTFOFF cbFree = 0;
    11461252    RTTESTI_CHECK_RC_RETV(RTFsQuerySizes(g_szDir, NULL, &cbFree, NULL, NULL), VINF_SUCCESS);
     
    13821488
    13831489
     1490/** For fsPerfIoRead and fsPerfIoWrite. */
     1491#define PROFILE_IO_FN(a_szOperation, a_fnCall) \
     1492    do \
     1493    { \
     1494        RTTESTI_CHECK_RC_RETV(RTFileSeek(hFile1, 0, RTFILE_SEEK_BEGIN, NULL), VINF_SUCCESS); \
     1495        uint64_t offActual = 0; \
     1496        uint32_t cSeeks    = 0; \
     1497        \
     1498        /* Estimate how many iterations we need to fill up the given timeslot: */ \
     1499        fsPerfYield(); \
     1500        uint64_t nsStart = RTTimeNanoTS(); \
     1501        uint64_t ns; \
     1502        do \
     1503            ns = RTTimeNanoTS(); \
     1504        while (ns == nsStart); \
     1505        nsStart = ns; \
     1506        \
     1507        uint64_t iIteration = 0; \
     1508        do \
     1509        { \
     1510            RTTESTI_CHECK_RC(a_fnCall, VINF_SUCCESS); \
     1511            iIteration++; \
     1512            ns = RTTimeNanoTS() - nsStart; \
     1513        } while (ns < RT_NS_10MS); \
     1514        ns /= iIteration; \
     1515        if (ns > g_nsPerNanoTSCall + 32) \
     1516            ns -= g_nsPerNanoTSCall; \
     1517        uint64_t cIterations = g_nsTestRun / ns; \
     1518        \
     1519        /* Do the actual profiling: */ \
     1520        cSeeks = 0; \
     1521        iIteration = 0; \
     1522        fsPerfYield(); \
     1523        nsStart = RTTimeNanoTS(); \
     1524        for (uint32_t iAdjust = 0; iAdjust < 4; iAdjust++) \
     1525        { \
     1526            for (; iIteration < cIterations; iIteration++)\
     1527                RTTESTI_CHECK_RC(a_fnCall, VINF_SUCCESS); \
     1528            ns = RTTimeNanoTS() - nsStart;\
     1529            if (ns >= g_nsTestRun - (g_nsTestRun / 10)) \
     1530                break; \
     1531            cIterations += cIterations / 4; \
     1532            if (cIterations & 1) \
     1533                cIterations++; \
     1534            nsStart += g_nsPerNanoTSCall; \
     1535        } \
     1536        RTTestIValueF(ns / iIteration, \
     1537                      RTTESTUNIT_NS_PER_OCCURRENCE, a_szOperation "/seq/%RU32 latency", cbBlock); \
     1538        RTTestIValueF((uint64_t)iIteration * cbBlock / ((double)ns / RT_NS_1SEC), \
     1539                      RTTESTUNIT_BYTES_PER_SEC,     a_szOperation "/seq/%RU32 throughput", cbBlock); \
     1540        RTTestIValueF(iIteration, \
     1541                      RTTESTUNIT_CALLS,             a_szOperation "/seq/%RU32 calls", cbBlock); \
     1542        RTTestIValueF((uint64_t)iIteration * cbBlock, \
     1543                      RTTESTUNIT_BYTES,             a_szOperation "/seq/%RU32 bytes", cbBlock); \
     1544        RTTestIValueF(cSeeks, \
     1545                      RTTESTUNIT_OCCURRENCES,       a_szOperation "/seq/%RU32 seeks", cbBlock); \
     1546        if (g_fShowDuration) \
     1547            RTTestIValueF(ns, RTTESTUNIT_NS,        a_szOperation "/seq/%RU32 duration", cbBlock); \
     1548    } while (0)
     1549
     1550
    13841551DECL_FORCE_INLINE(int) fsPerfIoReadWorker(RTFILE hFile1, uint64_t cbFile, uint32_t cbBlock, uint8_t *pbBlock,
    13851552                                          uint64_t *poffActual, uint32_t *pcSeeks)
     
    14081575
    14091576
    1410 void fsPerfIoRead(RTFILE hFile1, uint64_t cbFile, uint32_t cbBlock, uint8_t **ppbFree)
    1411 {
    1412     RTTestISubF("read %RU32", cbBlock);
    1413 
    1414     uint8_t *pbBuf = *ppbFree = (uint8_t *)RTMemPageAlloc(cbBlock);
    1415     if (!pbBuf)
    1416     {
     1577void fsPerfIoReadBlockSize(RTFILE hFile1, uint64_t cbFile, uint32_t cbBlock)
     1578{
     1579    RTTestISubF("Sequential read %RU32", cbBlock);
     1580
     1581    uint8_t *pbBuf = (uint8_t *)RTMemPageAlloc(cbBlock);
     1582    if (pbBuf)
     1583    {
     1584        memset(pbBuf, 0xf7, cbBlock);
     1585        PROFILE_IO_FN("RTFileRead", fsPerfIoReadWorker(hFile1, cbFile, cbBlock, pbBuf, &offActual, &cSeeks));
     1586        RTMemPageFree(pbBuf, cbBlock);
     1587    }
     1588    else
    14171589        RTTestSkipped(g_hTest, "insufficient (virtual) memory available");
    1418         return;
    1419     }
    1420 
    1421     char szDesc[64];
    1422     RTStrPrintf(szDesc, sizeof(szDesc), "RTFileRead/seq/%RU32", cbBlock);
    1423 
    1424     RTTESTI_CHECK_RC_RETV(RTFileSeek(hFile1, 0, RTFILE_SEEK_BEGIN, NULL), VINF_SUCCESS);
    1425     uint64_t offActual = 0;
    1426     uint32_t cSeeks    = 0;
    1427 
    1428     /* Estimate how many iterations we need to fill up the given timeslot: */
    1429     fsPerfYield();
    1430     uint64_t nsStart = RTTimeNanoTS();
    1431     uint64_t ns;
    1432     do
    1433         ns = RTTimeNanoTS();
    1434     while (ns == nsStart);
    1435     nsStart = ns;
    1436 
    1437     uint32_t iIteration = 0;
    1438     do
    1439     {
    1440         RTTESTI_CHECK_RC_RETV(fsPerfIoReadWorker(hFile1, cbFile, cbBlock, pbBuf, &offActual, &cSeeks), VINF_SUCCESS);
    1441         iIteration++;
    1442         ns = RTTimeNanoTS() - nsStart;
    1443     } while (ns < RT_NS_10MS);
    1444     ns /= iIteration;
    1445     if (ns > g_nsPerNanoTSCall)
    1446         ns -= g_nsPerNanoTSCall;
    1447     uint32_t const cIterations = g_nsTestRun / ns;
    1448 
    1449     /* Do the actual profiling: */
    1450     cSeeks = 0;
    1451     fsPerfYield();
    1452     nsStart = RTTimeNanoTS();
    1453     for (iIteration = 0; iIteration < cIterations; iIteration++)
    1454     {
    1455         fsPerfIoReadWorker(hFile1, cbFile, cbBlock, pbBuf, &offActual, &cSeeks);
    1456     }
    1457     ns = RTTimeNanoTS() - nsStart;
    1458     RTTestIValueF(ns / iIteration,
    1459                   RTTESTUNIT_NS_PER_OCCURRENCE, "RTFileRead/seq/%RU32 latency", cbBlock);
    1460     RTTestIValueF((uint64_t)iIteration * cbBlock / ((double)ns / RT_NS_1SEC),
    1461                   RTTESTUNIT_BYTES_PER_SEC,     "RTFileRead/seq/%RU32 throughput", cbBlock);
    1462     RTTestIValueF(iIteration,
    1463                   RTTESTUNIT_CALLS,             "RTFileRead/seq/%RU32 calls", cbBlock);
    1464     RTTestIValueF((uint64_t)iIteration * cbBlock,
    1465                   RTTESTUNIT_BYTES,             "RTFileRead/seq/%RU32 bytes", cbBlock);
    1466     RTTestIValueF(cSeeks,
    1467                   RTTESTUNIT_OCCURRENCES,       "RTFileRead/seq/%RU32 seeks", cbBlock);
    1468 }
    1469 
    1470 
    1471 void fsPerfIoWrite(RTFILE hFile1, uint64_t cbFile, uint32_t cbBlock, uint8_t **ppbFree)
    1472 {
    1473     RT_NOREF(hFile1, cbFile, cbBlock, ppbFree);
     1590}
     1591
     1592
     1593DECL_FORCE_INLINE(int) fsPerfIoWriteWorker(RTFILE hFile1, uint64_t cbFile, uint32_t cbBlock, uint8_t *pbBlock,
     1594                                           uint64_t *poffActual, uint32_t *pcSeeks)
     1595{
     1596    /* Do we need to seek back to the start? */
     1597    if (*poffActual + cbBlock <= cbFile)
     1598    { /* likely */ }
     1599    else
     1600    {
     1601        RTTESTI_CHECK_RC_RET(RTFileSeek(hFile1, 0, RTFILE_SEEK_BEGIN, NULL), VINF_SUCCESS, rcCheck);
     1602        *pcSeeks += 1;
     1603        *poffActual = 0;
     1604    }
     1605
     1606    size_t cbActuallyWritten = 0;
     1607    RTTESTI_CHECK_RC_RET(RTFileWrite(hFile1, pbBlock, cbBlock, &cbActuallyWritten), VINF_SUCCESS, rcCheck);
     1608    if (cbActuallyWritten == cbBlock)
     1609    {
     1610        *poffActual += cbActuallyWritten;
     1611        return VINF_SUCCESS;
     1612    }
     1613    RTTestIFailed("RTFileWrite at %#RX64 returned just %#x bytes, expected %#x", *poffActual, cbActuallyWritten, cbBlock);
     1614    *poffActual += cbActuallyWritten;
     1615    return VERR_WRITE_ERROR;
     1616}
     1617
     1618void fsPerfIoWriteBlockSize(RTFILE hFile1, uint64_t cbFile, uint32_t cbBlock)
     1619{
     1620    RTTestISubF("Sequential write %RU32", cbBlock);
     1621
     1622    uint8_t *pbBuf = (uint8_t *)RTMemPageAlloc(cbBlock);
     1623    if (pbBuf)
     1624    {
     1625        memset(pbBuf, 0xf7, cbBlock);
     1626        PROFILE_IO_FN("RTFileWrite", fsPerfIoWriteWorker(hFile1, cbFile, cbBlock, pbBuf, &offActual, &cSeeks));
     1627        RTMemPageFree(pbBuf, cbBlock);
     1628    }
     1629    else
     1630        RTTestSkipped(g_hTest, "insufficient (virtual) memory available");
    14741631}
    14751632
     
    15251682            fsPerfIoSeek(hFile1, cbFile);
    15261683        if (g_fRead)
     1684        {
    15271685            for (unsigned i = 0; i < g_cIoBlocks; i++)
    1528             {
    1529                 pbFree = NULL;
    1530                 fsPerfIoRead(hFile1, cbFile, g_acbIoBlocks[i], &pbFree);
    1531                 RTMemPageFree(pbFree, g_acbIoBlocks[i]);
    1532             }
     1686                fsPerfIoReadBlockSize(hFile1, cbFile, g_acbIoBlocks[i]);
     1687        }
    15331688        if (g_fWrite)
     1689        {
    15341690            for (unsigned i = 0; i < g_cIoBlocks; i++)
    1535             {
    1536                 pbFree = NULL;
    1537                 fsPerfIoWrite(hFile1, cbFile, g_acbIoBlocks[i], &pbFree);
    1538                 RTMemPageFree(pbFree, g_acbIoBlocks[i]);
    1539             }
     1691                fsPerfIoWriteBlockSize(hFile1, cbFile, g_acbIoBlocks[i]);
     1692        }
    15401693    }
    15411694
     
    17491902        {
    17501903            RTTestIPrintf(RTTESTLVL_ALWAYS, "Test  dir: %s\n", g_szDir);
    1751 
    1752             /* The empty subdir and associated globals: */
    1753             static char s_szEmpty[] = "empty";
    1754             memcpy(g_szEmptyDir, g_szDir, g_cchDir);
    1755             memcpy(&g_szEmptyDir[g_cchDir], s_szEmpty, sizeof(s_szEmpty));
    1756             g_cchEmptyDir = g_cchDir + sizeof(s_szEmpty) - 1;
    1757             rc = RTDirCreate(g_szEmptyDir, 0755, 0);
     1904            rc = fsPrepTestArea();
    17581905            if (RT_SUCCESS(rc))
    17591906            {
    1760                 g_szEmptyDir[g_cchEmptyDir++] = RTPATH_SLASH;
    1761                 g_szEmptyDir[g_cchEmptyDir]   = '\0';
    1762                 RTTestIPrintf(RTTESTLVL_ALWAYS, "Empty dir: %s\n", g_szEmptyDir);
    1763 
    1764                 /* Deep directory: */
    1765                 memcpy(g_szDeepDir, g_szDir, g_cchDir);
    1766                 g_cchDeepDir = g_cchDir;
    1767                 do
    1768                 {
    1769                     static char const s_szSub[] = "d" RTPATH_SLASH_STR;
    1770                     memcpy(&g_szDeepDir[g_cchDeepDir], s_szSub, sizeof(s_szSub));
    1771                     g_cchDeepDir += sizeof(s_szSub) - 1;
    1772                     RTTESTI_CHECK_RC(rc = RTDirCreate(g_szDeepDir, 0755, 0), VINF_SUCCESS);
    1773                 } while (RT_SUCCESS(rc) && g_cchDeepDir < 176);
    1774                 RTTestIPrintf(RTTESTLVL_ALWAYS, "Deep  dir: %s\n", g_szDeepDir);
    1775                 if (RT_SUCCESS(rc))
    1776                 {
    1777                     /* Profile RTTimeNanoTS(). */
    1778                     fsPerfNanoTS();
    1779 
    1780                     /* Do tests: */
    1781                     if (g_fManyFiles)
    1782                         fsPerfManyFiles();
    1783                     if (g_fOpen)
    1784                         fsPerfOpen();
    1785                     if (g_fFStat)
    1786                         fsPerfFStat();
    1787                     if (g_fFChMod)
    1788                         fsPerfFChMod();
    1789                     if (g_fFUtimes)
    1790                         fsPerfFUtimes();
    1791                     if (g_fStat)
    1792                         fsPerfStat();
    1793                     if (g_fChMod)
    1794                         fsPerfChmod();
    1795                     if (g_fUtimes)
    1796                         fsPerfUtimes();
    1797                     if (g_fRename)
    1798                         fsPerfRename();
    1799                     if (g_fDirEnum)
    1800                         vsPerfDirEnum();
    1801                     if (g_fMkRmDir)
    1802                         fsPerfMkRmDir();
    1803                     if (g_fStatVfs)
    1804                         fsPerfStatVfs();
    1805                     if (g_fRm || g_fManyFiles)
    1806                         fsPerfRm(); /* deletes manyfiles and manytree */
    1807                     if (g_fChSize)
    1808                         fsPerfChSize();
    1809                     if (g_fRead || g_fWrite || g_fSeek)
    1810                         fsPerfIo();
    1811                 }
     1907                /* Profile RTTimeNanoTS(). */
     1908                fsPerfNanoTS();
     1909
     1910                /* Do tests: */
     1911                if (g_fManyFiles)
     1912                    fsPerfManyFiles();
     1913                if (g_fOpen)
     1914                    fsPerfOpen();
     1915                if (g_fFStat)
     1916                    fsPerfFStat();
     1917                if (g_fFChMod)
     1918                    fsPerfFChMod();
     1919                if (g_fFUtimes)
     1920                    fsPerfFUtimes();
     1921                if (g_fStat)
     1922                    fsPerfStat();
     1923                if (g_fChMod)
     1924                    fsPerfChmod();
     1925                if (g_fUtimes)
     1926                    fsPerfUtimes();
     1927                if (g_fRename)
     1928                    fsPerfRename();
     1929                if (g_fDirEnum)
     1930                    vsPerfDirEnum();
     1931                if (g_fMkRmDir)
     1932                    fsPerfMkRmDir();
     1933                if (g_fStatVfs)
     1934                    fsPerfStatVfs();
     1935                if (g_fRm || g_fManyFiles)
     1936                    fsPerfRm(); /* deletes manyfiles and manytree */
     1937                if (g_fChSize)
     1938                    fsPerfChSize();
     1939                if (g_fRead || g_fWrite || g_fSeek)
     1940                    fsPerfIo();
    18121941            }
    18131942
Note: See TracChangeset for help on using the changeset viewer.

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