VirtualBox

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


Ignore:
Timestamp:
Jan 21, 2019 12:19:00 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
128285
Message:

FsPerf: Mostly done on windows. bugref:9172

File:
1 edited

Legend:

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

    r76903 r76914  
    251251    kCmdOpt_Seek,
    252252    kCmdOpt_NoSeek,
     253    kCmdOpt_FSync,
     254    kCmdOpt_NoFSync,
     255    kCmdOpt_MMap,
     256    kCmdOpt_NoMMap,
    253257
    254258    kCmdOpt_End
     
    259263*   Global Variables                                                                                                             *
    260264*********************************************************************************************************************************/
    261 
    262265/** Command line parameters */
    263266static const RTGETOPTDEF g_aCmdOptions[] =
     
    305308    { "--seek",             kCmdOpt_Seek,           RTGETOPT_REQ_NOTHING },
    306309    { "--no-seek",          kCmdOpt_NoSeek,         RTGETOPT_REQ_NOTHING },
     310    { "--fsync",            kCmdOpt_FSync,          RTGETOPT_REQ_NOTHING },
     311    { "--no-fsync",         kCmdOpt_NoFSync,        RTGETOPT_REQ_NOTHING },
     312    { "--mmap",             kCmdOpt_MMap,           RTGETOPT_REQ_NOTHING },
     313    { "--no-mmap",          kCmdOpt_NoMMap,         RTGETOPT_REQ_NOTHING },
    307314
    308315    { "--quiet",            'q', RTGETOPT_REQ_NOTHING },
     
    339346static bool         g_fRm        = true;
    340347static bool         g_fChSize    = true;
    341 static bool         g_fSeek      = true;
    342348static bool         g_fRead      = true;
    343349static bool         g_fWrite     = true;
     350static bool         g_fSeek      = true;
     351static bool         g_fFSync     = true;
     352static bool         g_fMMap      = true;
    344353/** @} */
    345354
     
    13921401 * Checks the content read from the file fsPerfIoPrepFile() prepared.
    13931402 */
    1394 bool fsPrefCheckReadBuf(unsigned uLineNo, uint64_t off, uint8_t const *pbBuf, size_t cbBuf, uint8_t bFiller = 0xf6)
     1403bool fsPerfCheckReadBuf(unsigned uLineNo, uint64_t off, uint8_t const *pbBuf, size_t cbBuf, uint8_t bFiller = 0xf6)
    13951404{
    13961405    uint32_t cMismatches = 0;
     
    14541463 * Sets up write buffer with offset markers and fillers.
    14551464 */
    1456 void fsPrefFillWriteBuf(uint64_t off, uint8_t *pbBuf, size_t cbBuf, uint8_t bFiller = 0xf6)
     1465void fsPerfFillWriteBuf(uint64_t off, uint8_t *pbBuf, size_t cbBuf, uint8_t bFiller = 0xf6)
    14571466{
    14581467    uint32_t offBlock = (uint32_t)(off & (_1K - 1));
     
    17531762            }
    17541763        }
    1755         fsPrefCheckReadBuf(__LINE__, aRuns[i].offFile, pbBuf, cbBuf);
     1764        fsPerfCheckReadBuf(__LINE__, aRuns[i].offFile, pbBuf, cbBuf);
    17561765    }
    17571766#endif
     
    18351844        }
    18361845    }
    1837     fsPrefCheckReadBuf(__LINE__, 0, pbBuf, cbBuf);
     1846    fsPerfCheckReadBuf(__LINE__, 0, pbBuf, cbBuf);
    18381847
    18391848    /*
     
    18721881    RTTESTI_CHECK(Ios.Information == _4K);
    18731882    RTTESTI_CHECK(RTFileTell(hFile1) == cbFile / 2 + _4K);
    1874     fsPrefCheckReadBuf(__LINE__, cbFile / 2, pbBuf, _4K);
     1883    fsPerfCheckReadBuf(__LINE__, cbFile / 2, pbBuf, _4K);
    18751884#endif
    18761885
     
    19521961    for (uint32_t i = 0; i < RT_ELEMENTS(aRuns); i++, bFiller)
    19531962    {
    1954         fsPrefFillWriteBuf(aRuns[i].offFile, pbBuf, cbBuf, bFiller);
    1955         fsPrefCheckReadBuf(__LINE__, aRuns[i].offFile, pbBuf, cbBuf, bFiller);
     1963        fsPerfFillWriteBuf(aRuns[i].offFile, pbBuf, cbBuf, bFiller);
     1964        fsPerfCheckReadBuf(__LINE__, aRuns[i].offFile, pbBuf, cbBuf, bFiller);
    19561965
    19571966        RTTESTI_CHECK_RC(RTFileSeek(hFile1, aRuns[i].offFile, RTFILE_SEEK_BEGIN, NULL), VINF_SUCCESS);
     
    19771986
    19781987        RTTESTI_CHECK_RC(RTFileReadAt(hFile1, aRuns[i].offFile, pbBuf, cbBuf, NULL), VINF_SUCCESS);
    1979         fsPrefCheckReadBuf(__LINE__, aRuns[i].offFile, pbBuf, cbBuf, bFiller);
     1988        fsPerfCheckReadBuf(__LINE__, aRuns[i].offFile, pbBuf, cbBuf, bFiller);
    19801989    }
    19811990
     
    19871996    for (unsigned iFile = 0; iFile < RT_ELEMENTS(ahFiles); iFile++, bFiller++)
    19881997    {
    1989         fsPrefFillWriteBuf(0, pbBuf, cbBuf, bFiller);
    1990         fsPrefCheckReadBuf(__LINE__, 0, pbBuf, cbBuf, bFiller);
     1998        fsPerfFillWriteBuf(0, pbBuf, cbBuf, bFiller);
     1999        fsPerfCheckReadBuf(__LINE__, 0, pbBuf, cbBuf, bFiller);
    19912000        RTTESTI_CHECK_RC(RTFileSeek(ahFiles[iFile], 0, RTFILE_SEEK_BEGIN, NULL), VINF_SUCCESS);
    19922001
     
    20022011            {
    20032012                RTTESTI_CHECK_RC(RTFileReadAt(hFile1, offBuf, pbBuf, cbToWrite, NULL), VINF_SUCCESS);
    2004                 fsPrefCheckReadBuf(__LINE__, offBuf, pbBuf, cbToWrite, bFiller);
     2013                fsPerfCheckReadBuf(__LINE__, offBuf, pbBuf, cbToWrite, bFiller);
    20052014                offBuf += cbActual;
    20062015            }
     
    20192028
    20202029        RTTESTI_CHECK_RC(RTFileReadAt(ahFiles[iFile], 0, pbBuf, cbBuf, NULL), VINF_SUCCESS);
    2021         fsPrefCheckReadBuf(__LINE__, 0, pbBuf, cbBuf, bFiller);
     2030        fsPerfCheckReadBuf(__LINE__, 0, pbBuf, cbBuf, bFiller);
    20222031    }
    20232032
     
    20362045
    20372046    RTTESTI_CHECK_RC(RTFileRead(hFile1, pbBuf, _4K, NULL), VINF_SUCCESS);
    2038     fsPrefCheckReadBuf(__LINE__, cbFile - _4K, pbBuf, _4K, pbBuf[0x8]);
     2047    fsPerfCheckReadBuf(__LINE__, cbFile - _4K, pbBuf, _4K, pbBuf[0x8]);
    20392048#endif
    20402049
     
    20602069    RT_NOREF(hFileNoCache, hFileWriteThru);
    20612070    RTMemPageFree(pbBuf, cbBuf);
     2071}
     2072
     2073
     2074/**
     2075 * Worker for testing RTFileFlush.
     2076 */
     2077DECL_FORCE_INLINE(int) fsPerfFSyncWorker(RTFILE hFile1, uint64_t cbFile, uint8_t *pbBuf, size_t cbBuf, uint64_t *poffFile)
     2078{
     2079    if (*poffFile + cbBuf <= cbFile)
     2080    { /* likely */ }
     2081    else
     2082    {
     2083        RTTESTI_CHECK_RC(RTFileSeek(hFile1, 0, RTFILE_SEEK_BEGIN, NULL), VINF_SUCCESS);
     2084        *poffFile = 0;
     2085    }
     2086
     2087    RTTESTI_CHECK_RC_RET(RTFileWrite(hFile1, pbBuf, cbBuf, NULL), VINF_SUCCESS, rcCheck);
     2088    RTTESTI_CHECK_RC_RET(RTFileFlush(hFile1), VINF_SUCCESS, rcCheck);
     2089
     2090    *poffFile += cbBuf;
     2091    return VINF_SUCCESS;
     2092}
     2093
     2094
     2095void fsPerfFSync(RTFILE hFile1, uint64_t cbFile)
     2096{
     2097    RTTestISub("fsync");
     2098
     2099    RTTESTI_CHECK_RC(RTFileFlush(hFile1), VINF_SUCCESS);
     2100
     2101    PROFILE_FN(RTFileFlush(hFile1), g_nsTestRun, "RTFileFlush");
     2102
     2103    size_t   cbBuf = PAGE_SIZE;
     2104    uint8_t *pbBuf = (uint8_t *)RTMemPageAlloc(cbBuf);
     2105    RTTESTI_CHECK_RETV(pbBuf != NULL);
     2106    memset(pbBuf, 0xf4, cbBuf);
     2107
     2108    RTTESTI_CHECK_RC(RTFileSeek(hFile1, 0, RTFILE_SEEK_BEGIN, NULL), VINF_SUCCESS);
     2109    uint64_t offFile = 0;
     2110    PROFILE_FN(fsPerfFSyncWorker(hFile1, cbFile, pbBuf, cbBuf, &offFile), g_nsTestRun, "RTFileWrite[Page]/RTFileFlush");
     2111
     2112    RTMemPageFree(pbBuf, cbBuf);
     2113}
     2114
     2115
     2116void fsPerfMMap(RTFILE hFile1, RTFILE hFileNoCache, uint64_t cbFile)
     2117{
     2118    RTTestISub("mmap");
     2119#if defined(RT_OS_WINDOWS)
     2120    static const char * const s_apszStates[] = { "readonly", "writecopy", "readwrite" };
     2121    enum { kMMap_ReadOnly = 0, kMMap_WriteCopy, kMMap_ReadWrite, kMMap_End };
     2122    for (int enmState = kMMap_ReadOnly; enmState < kMMap_End; enmState++)
     2123    {
     2124        /*
     2125         * Do the mapping.
     2126         */
     2127        size_t cbMapping = (size_t)cbFile;
     2128        if (cbMapping != cbFile)
     2129            cbMapping = _256M;
     2130        uint8_t *pbMapping;
     2131
     2132# ifdef RT_OS_WINDOWS
     2133        HANDLE hSection;
     2134        for (;; cbMapping /= 2)
     2135        {
     2136            hSection = CreateFileMapping((HANDLE)RTFileToNative(hFile1), NULL,
     2137                                         enmState == kMMap_ReadOnly    ? PAGE_READONLY
     2138                                         : enmState == kMMap_WriteCopy ? PAGE_WRITECOPY : PAGE_READWRITE,
     2139                                         (uint32_t)(cbMapping >> 32), (uint32_t)cbMapping, NULL);
     2140            DWORD dwErr1 = GetLastError();
     2141            DWORD dwErr2 = 0;
     2142            if (hSection != NULL)
     2143            {
     2144                pbMapping = (uint8_t *)MapViewOfFile(hSection,
     2145                                                     enmState == kMMap_ReadOnly    ? FILE_MAP_READ
     2146                                                     : enmState == kMMap_WriteCopy ? FILE_MAP_COPY
     2147                                                     :                               FILE_MAP_WRITE,
     2148                                                     0, 0, cbMapping);
     2149                if (pbMapping)
     2150                    break;
     2151                dwErr2 = GetLastError();
     2152                CloseHandle(hSection);
     2153            }
     2154            if (cbMapping <= _2M)
     2155            {
     2156                RTTestIFailed("%u: CreateFileMapping or MapViewOfFile failed: %u, %u", enmState, dwErr1, dwErr2);
     2157                return;
     2158            }
     2159        }
     2160# else
     2161        for (;; cbMapping /= 2)
     2162        {
     2163            pbMapping = (uint8_t *)mmap(NULL, cbMapping,
     2164                                        enmState == kMMap_ReadOnly  ? PROT_READ   : PROT_READ | PROT_WRITE,
     2165                                        enmState == kMMap_WriteCopy ? MAP_PRIVATE : MAP_SHARED,
     2166                                        (int)RTFileToNative(hFile1), cbMapping);
     2167            if ((void *)pbMapping != MAP_FAILED)
     2168                break;
     2169            RTTESTI_CHECK_MSG_RETV(cbMapping > _2M, ("errno=%d", errno));
     2170        }
     2171# endif
     2172
     2173        /*
     2174         * Time page-ins just for fun.
     2175         */
     2176        size_t const cPages = cbMapping >> PAGE_SHIFT;
     2177        size_t uDummy = 0;
     2178        uint64_t ns = RTTimeNanoTS();
     2179        for (size_t iPage = 0; iPage < cPages; iPage++)
     2180            uDummy += ASMAtomicReadU8(&pbMapping[iPage << PAGE_SHIFT]);
     2181        ns = RTTimeNanoTS() - ns;
     2182        RTTestIValueF(ns / cPages, RTTESTUNIT_NS_PER_OCCURRENCE,  "page-in %s", s_apszStates[enmState]);
     2183
     2184        /* Check the content. */
     2185        fsPerfCheckReadBuf(__LINE__, 0, pbMapping, cbMapping);
     2186
     2187        if (enmState != kMMap_ReadOnly)
     2188        {
     2189            /* Write stuff to the first two megabytes.  In the COW case, we'll detect
     2190               corruption of shared data during content checking of the RW iterations. */
     2191            fsPerfFillWriteBuf(0, pbMapping, _2M, 0xf7);
     2192            if (enmState == kMMap_ReadWrite)
     2193            {
     2194                /* For RW we can try read back from the file handle and check if we get
     2195                   a match there first.  */
     2196                uint8_t abBuf[_4K];
     2197                for (uint32_t off = 0; off < _2M; off += sizeof(abBuf))
     2198                {
     2199                    RTTESTI_CHECK_RC(RTFileReadAt(hFile1, off, abBuf, sizeof(abBuf), NULL), VINF_SUCCESS);
     2200                    fsPerfCheckReadBuf(__LINE__, off, abBuf, sizeof(abBuf), 0xf7);
     2201                }
     2202# ifdef RT_OS_WINDOWS
     2203                RTTESTI_CHECK(FlushViewOfFile(pbMapping, _2M));
     2204# else
     2205                RTTESTI_CHECK(msync(pbMapping, _2M, MS_SYNC) == 0);
     2206# endif
     2207
     2208                /*
     2209                 * Time modifying and flushing a few different number of pages.
     2210                 */
     2211                static size_t const s_acbFlush[] = { PAGE_SIZE, PAGE_SIZE * 2, PAGE_SIZE * 3, PAGE_SIZE * 8, PAGE_SIZE * 16, _2M };
     2212                for (unsigned iFlushSize = 0 ; iFlushSize < RT_ELEMENTS(s_acbFlush); iFlushSize++)
     2213                {
     2214                    size_t const cbFlush = s_acbFlush[iFlushSize];
     2215                    if (cbFlush > cbMapping)
     2216                        continue;
     2217
     2218                    size_t const cFlushes = cbMapping / cbFlush;
     2219                    uint8_t     *pbCur    = pbMapping;
     2220                    ns = RTTimeNanoTS();
     2221                    for (size_t iFlush = 0; iFlush < cFlushes; iFlush++, pbCur += cbFlush)
     2222                    {
     2223                        for (size_t offFlush = 0; offFlush < cbFlush; offFlush += PAGE_SIZE)
     2224                            *(size_t volatile *)&pbCur[offFlush + 8] = cbFlush;
     2225# ifdef RT_OS_WINDOWS
     2226                        RTTESTI_CHECK(FlushViewOfFile(pbCur, cbFlush));
     2227# else
     2228                        RTTESTI_CHECK(msync(pbCur, cbFlush, MS_SYNC) == 0);
     2229# endif
     2230                    }
     2231                    ns = RTTimeNanoTS() - ns;
     2232                    RTTestIValueF(ns / cPages, RTTESTUNIT_NS_PER_OCCURRENCE,  "touch/flush/%zu", cbFlush);
     2233
     2234                    /*
     2235                     * Check that all the changes made it thru to the file:
     2236                     */
     2237                    size_t   cbBuf = _2M;
     2238                    uint8_t *pbBuf = (uint8_t *)RTMemPageAlloc(_2M);
     2239                    if (!pbBuf)
     2240                    {
     2241                        cbBuf = _4K;
     2242                        pbBuf = (uint8_t *)RTMemPageAlloc(_2M);
     2243                    }
     2244                    if (pbBuf)
     2245                    {
     2246                        RTTESTI_CHECK_RC(RTFileSeek(hFileNoCache, 0, RTFILE_SEEK_BEGIN, NULL), VINF_SUCCESS);
     2247                        size_t const cbToCheck = cFlushes * cbFlush;
     2248                        unsigned     cErrors   = 0;
     2249                        for (size_t offBuf = 0; cErrors < 32 && offBuf < cbToCheck; offBuf += cbBuf)
     2250                        {
     2251                            size_t cbToRead = RT_MIN(cbBuf, cbToCheck - offBuf);
     2252                            RTTESTI_CHECK_RC(RTFileRead(hFileNoCache, pbBuf, cbToRead, NULL), VINF_SUCCESS);
     2253
     2254                            for (size_t offFlush = 0; offFlush < cbToRead; offFlush += PAGE_SIZE)
     2255                                if (*(size_t volatile *)&pbBuf[offFlush + 8] != cbFlush)
     2256                                {
     2257                                    RTTestIFailed("Flush issue at offset #%zx: %#zx, expected %#zx (cbFlush=%#zx)",
     2258                                                  offBuf, *(size_t volatile *)&pbBuf[offFlush + 8], cbFlush, cbFlush);
     2259                                    if (++cErrors > 32)
     2260                                        break;
     2261                                }
     2262                        }
     2263                        RTMemPageFree(pbBuf, cbBuf);
     2264                    }
     2265                }
     2266            }
     2267        }
     2268
     2269        /*
     2270         * Unmap it.
     2271         */
     2272# ifdef RT_OS_WINDOWS
     2273        RTTESTI_CHECK(UnmapViewOfFile(pbMapping));
     2274        RTTESTI_CHECK(CloseHandle(hSection));
     2275# else
     2276        RTTESTI_CHECK(munmap(pbMapping, cbMapping) == 0);
     2277# endif
     2278    }
     2279
     2280    RT_NOREF(hFileNoCache);
     2281#else
     2282    RTTestSkipped(g_hTest,  "not supported/implemented");
     2283    RT_NOREF(hFile1, hFileNoCache, cbFile);
     2284#endif
    20622285}
    20632286
     
    21272350                fsPerfIoReadBlockSize(hFile1, cbFile, g_acbIoBlocks[i]);
    21282351        }
    2129         /** @todo mmap */
    2130 
     2352        if (g_fMMap)
     2353            fsPerfMMap(hFile1, hFileNoCache, cbFile);
    21312354        if (g_fWrite)
    21322355        {
     
    21362359                fsPerfIoWriteBlockSize(hFile1, cbFile, g_acbIoBlocks[i]);
    21372360        }
    2138 
     2361        if (g_fFSync)
     2362            fsPerfFSync(hFile1, cbFile);
    21392363    }
    21402364
     
    22682492                g_fWrite     = true;
    22692493                g_fSeek      = true;
     2494                g_fFSync     = true;
     2495                g_fMMap      = true;
    22702496                break;
    22712497
     
    22882514                g_fWrite     = false;
    22892515                g_fSeek      = false;
     2516                g_fFSync     = false;
     2517                g_fMMap      = false;
    22902518                break;
    22912519
     
    23072535            CASE_OPT(Rm);
    23082536            CASE_OPT(ChSize);
    2309             CASE_OPT(Seek);
    23102537            CASE_OPT(Read);
    23112538            CASE_OPT(Write);
     2539            CASE_OPT(Seek);
     2540            CASE_OPT(FSync);
     2541            CASE_OPT(MMap);
    23122542#undef CASE_OPT
    23132543
     
    23852615                if (g_fChSize)
    23862616                    fsPerfChSize();
    2387                 if (g_fRead || g_fWrite || g_fSeek)
     2617                if (g_fRead || g_fWrite || g_fSeek || g_fFSync || g_fMMap)
    23882618                    fsPerfIo();
    23892619            }
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