- Timestamp:
- Jan 26, 2019 12:24:28 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 128421
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/fs/FsPerf.cpp
r76975 r76999 267 267 kCmdOpt_MMap, 268 268 kCmdOpt_NoMMap, 269 kCmdOpt_IgnoreNoCache, 270 kCmdOpt_NoIgnoreNoCache, 271 kCmdOpt_IoFileSize, 272 kCmdOpt_SetBlockSize, 273 kCmdOpt_AddBlockSize, 269 274 270 275 kCmdOpt_ShowDuration, … … 272 277 kCmdOpt_ShowIterations, 273 278 kCmdOpt_NoShowIterations, 279 280 kCmdOpt_ManyTreeFilesPerDir, 281 kCmdOpt_ManyTreeSubdirsPerDir, 282 kCmdOpt_ManyTreeDepth, 283 274 284 kCmdOpt_End 275 285 }; … … 289 299 { "--disable-all", 'z', RTGETOPT_REQ_NOTHING }, 290 300 291 { "--many-files", kCmdOpt_ManyFiles, RTGETOPT_REQ_NOTHING }, 292 { "--no-many-files", kCmdOpt_NoManyFiles, RTGETOPT_REQ_NOTHING }, 301 { "--many-files", kCmdOpt_ManyFiles, RTGETOPT_REQ_UINT32 }, 302 { "--no-many-files", kCmdOpt_NoManyFiles, RTGETOPT_REQ_NOTHING }, 303 { "--files-per-dir", kCmdOpt_ManyTreeFilesPerDir, RTGETOPT_REQ_UINT32 }, 304 { "--subdirs-per-dir", kCmdOpt_ManyTreeSubdirsPerDir, RTGETOPT_REQ_UINT32 }, 305 { "--tree-depth", kCmdOpt_ManyTreeDepth, RTGETOPT_REQ_UINT32 }, 293 306 294 307 { "--open", kCmdOpt_Open, RTGETOPT_REQ_NOTHING }, … … 328 341 { "--mmap", kCmdOpt_MMap, RTGETOPT_REQ_NOTHING }, 329 342 { "--no-mmap", kCmdOpt_NoMMap, RTGETOPT_REQ_NOTHING }, 343 { "--ignore-no-cache", kCmdOpt_IgnoreNoCache, RTGETOPT_REQ_NOTHING }, 344 { "--no-ignore-no-cache", kCmdOpt_NoIgnoreNoCache, RTGETOPT_REQ_NOTHING }, 345 { "--io-file-size", kCmdOpt_IoFileSize, RTGETOPT_REQ_UINT64 }, 346 { "--set-block-size", kCmdOpt_SetBlockSize, RTGETOPT_REQ_UINT32 }, 347 { "--add-block-size", kCmdOpt_AddBlockSize, RTGETOPT_REQ_UINT32 }, 330 348 331 349 { "--show-duration", kCmdOpt_ShowDuration, RTGETOPT_REQ_NOTHING }, … … 387 405 /** Number of files per directory in the 'manytree' construct. */ 388 406 static uint32_t g_cManyTreeFilesPerDir = 640; 389 /* Number of subdirs per directory in the 'manytree' construct. */407 /** Number of subdirs per directory in the 'manytree' construct. */ 390 408 static uint32_t g_cManyTreeSubdirsPerDir = 16; 391 409 /** The depth of the 'manytree' directory tree. */ … … 400 418 /** The desired size of the test file we use for I/O. */ 401 419 static uint64_t g_cbIoFile = _512M; 420 /** Whether to be less strict with non-cache file handle. */ 421 static bool g_fIgnoreNoCache = false; 402 422 403 423 /** The length of g_szDir. */ … … 1860 1880 uint32_t cbPage = PAGE_SIZE; 1861 1881 memset(pbBuf, 0x66, cbBuf); 1862 RTTESTI_CHECK_RC(RTFileSeek(hFileNoCache, 0, RTFILE_SEEK_BEGIN, NULL), VINF_SUCCESS); 1863 for (size_t offBuf = 0; offBuf < cbBuf; ) 1864 { 1865 uint32_t const cPagesLeft = (uint32_t)((cbBuf - offBuf) / cbPage); 1866 uint32_t const cPagesToRead = RTRandU32Ex(1, cPagesLeft); 1867 size_t const cbToRead = cPagesToRead * (size_t)cbPage; 1868 size_t cbActual = 0; 1869 RTTESTI_CHECK_RC(RTFileRead(hFileNoCache, &pbBuf[offBuf], cbToRead, &cbActual), VINF_SUCCESS); 1870 if (cbActual == cbToRead) 1871 offBuf += cbActual; 1872 else 1873 { 1874 RTTestIFailed("Attempting to read %#zx bytes at %#zx, only got %#x bytes back!\n", cbToRead, offBuf, cbActual); 1875 if (cbActual) 1882 if (!g_fIgnoreNoCache || hFileNoCache != NIL_RTFILE) 1883 { 1884 RTTESTI_CHECK_RC(RTFileSeek(hFileNoCache, 0, RTFILE_SEEK_BEGIN, NULL), VINF_SUCCESS); 1885 for (size_t offBuf = 0; offBuf < cbBuf; ) 1886 { 1887 uint32_t const cPagesLeft = (uint32_t)((cbBuf - offBuf) / cbPage); 1888 uint32_t const cPagesToRead = RTRandU32Ex(1, cPagesLeft); 1889 size_t const cbToRead = cPagesToRead * (size_t)cbPage; 1890 size_t cbActual = 0; 1891 RTTESTI_CHECK_RC(RTFileRead(hFileNoCache, &pbBuf[offBuf], cbToRead, &cbActual), VINF_SUCCESS); 1892 if (cbActual == cbToRead) 1876 1893 offBuf += cbActual; 1877 1894 else 1878 1895 { 1879 memset(&pbBuf[offBuf], 0x11, cbPage); 1880 offBuf += cbPage; 1896 RTTestIFailed("Attempting to read %#zx bytes at %#zx, only got %#x bytes back!\n", cbToRead, offBuf, cbActual); 1897 if (cbActual) 1898 offBuf += cbActual; 1899 else 1900 { 1901 memset(&pbBuf[offBuf], 0x11, cbPage); 1902 offBuf += cbPage; 1903 } 1881 1904 } 1882 1905 } 1883 }1884 fsPerfCheckReadBuf(__LINE__, 0, pbBuf, cbBuf);1906 fsPerfCheckReadBuf(__LINE__, 0, pbBuf, cbBuf); 1907 } 1885 1908 1886 1909 /* … … 2038 2061 for (unsigned iFile = 0; iFile < RT_ELEMENTS(ahFiles); iFile++, bFiller++) 2039 2062 { 2063 if (g_fIgnoreNoCache && ahFiles[iFile] == NIL_RTFILE) 2064 continue; 2065 2040 2066 fsPerfFillWriteBuf(0, pbBuf, cbBuf, bFiller); 2041 2067 fsPerfCheckReadBuf(__LINE__, 0, pbBuf, cbBuf, bFiller); … … 2111 2137 #endif 2112 2138 2113 RT_NOREF(hFileNoCache, hFileWriteThru);2114 2139 RTMemPageFree(pbBuf, cbBuf); 2115 2140 } … … 2292 2317 * Check that all the changes made it thru to the file: 2293 2318 */ 2294 size_t cbBuf = _2M; 2295 uint8_t *pbBuf = (uint8_t *)RTMemPageAlloc(_2M); 2296 if (!pbBuf) 2319 if (!g_fIgnoreNoCache || hFileNoCache != NIL_RTFILE) 2297 2320 { 2298 cbBuf = _4K; 2299 pbBuf = (uint8_t *)RTMemPageAlloc(_2M); 2300 } 2301 if (pbBuf) 2302 { 2303 RTTESTI_CHECK_RC(RTFileSeek(hFileNoCache, 0, RTFILE_SEEK_BEGIN, NULL), VINF_SUCCESS); 2304 size_t const cbToCheck = RT_MIN(cFlushes * cbFlush, cbFlushed); 2305 unsigned cErrors = 0; 2306 for (size_t offBuf = 0; cErrors < 32 && offBuf < cbToCheck; offBuf += cbBuf) 2321 size_t cbBuf = _2M; 2322 uint8_t *pbBuf = (uint8_t *)RTMemPageAlloc(_2M); 2323 if (!pbBuf) 2307 2324 { 2308 size_t cbToRead = RT_MIN(cbBuf, cbToCheck - offBuf); 2309 RTTESTI_CHECK_RC(RTFileRead(hFileNoCache, pbBuf, cbToRead, NULL), VINF_SUCCESS); 2310 2311 for (size_t offFlush = 0; offFlush < cbToRead; offFlush += PAGE_SIZE) 2312 if (*(size_t volatile *)&pbBuf[offFlush + 8] != cbFlush) 2313 { 2314 RTTestIFailed("Flush issue at offset #%zx: %#zx, expected %#zx (cbFlush=%#zx)", 2315 offBuf, *(size_t volatile *)&pbBuf[offFlush + 8], cbFlush, cbFlush); 2316 if (++cErrors > 32) 2317 break; 2318 } 2325 cbBuf = _4K; 2326 pbBuf = (uint8_t *)RTMemPageAlloc(_2M); 2319 2327 } 2320 RTMemPageFree(pbBuf, cbBuf); 2328 if (pbBuf) 2329 { 2330 RTTESTI_CHECK_RC(RTFileSeek(hFileNoCache, 0, RTFILE_SEEK_BEGIN, NULL), VINF_SUCCESS); 2331 size_t const cbToCheck = RT_MIN(cFlushes * cbFlush, cbFlushed); 2332 unsigned cErrors = 0; 2333 for (size_t offBuf = 0; cErrors < 32 && offBuf < cbToCheck; offBuf += cbBuf) 2334 { 2335 size_t cbToRead = RT_MIN(cbBuf, cbToCheck - offBuf); 2336 RTTESTI_CHECK_RC(RTFileRead(hFileNoCache, pbBuf, cbToRead, NULL), VINF_SUCCESS); 2337 2338 for (size_t offFlush = 0; offFlush < cbToRead; offFlush += PAGE_SIZE) 2339 if (*(size_t volatile *)&pbBuf[offFlush + 8] != cbFlush) 2340 { 2341 RTTestIFailed("Flush issue at offset #%zx: %#zx, expected %#zx (cbFlush=%#zx)", 2342 offBuf, *(size_t volatile *)&pbBuf[offFlush + 8], cbFlush, cbFlush); 2343 if (++cErrors > 32) 2344 break; 2345 } 2346 } 2347 RTMemPageFree(pbBuf, cbBuf); 2348 } 2321 2349 } 2322 2350 } … … 2383 2411 RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE | RTFILE_O_READWRITE), VINF_SUCCESS); 2384 2412 RTFILE hFileNoCache; 2385 RTTESTI_CHECK_RC_RETV(RTFileOpen(&hFileNoCache, g_szDir, 2386 RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READWRITE | RTFILE_O_NO_CACHE), 2387 VINF_SUCCESS); 2413 if (!g_fIgnoreNoCache) 2414 RTTESTI_CHECK_RC_RETV(RTFileOpen(&hFileNoCache, g_szDir, 2415 RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READWRITE | RTFILE_O_NO_CACHE), 2416 VINF_SUCCESS); 2417 else 2418 { 2419 int rc = RTFileOpen(&hFileNoCache, g_szDir, RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READWRITE | RTFILE_O_NO_CACHE); 2420 if (RT_FAILURE(rc)) 2421 { 2422 RTTestIPrintf(RTTESTLVL_ALWAYS, "Unable to open I/O file with non-cache flag (%Rrc), skipping related tests.\n", rc); 2423 hFileNoCache = NIL_RTFILE; 2424 } 2425 } 2388 2426 RTFILE hFileWriteThru; 2389 2427 RTTESTI_CHECK_RC_RETV(RTFileOpen(&hFileWriteThru, g_szDir, … … 2422 2460 RTTESTI_CHECK_RC(RTFileSetSize(hFile1, 0), VINF_SUCCESS); 2423 2461 RTTESTI_CHECK_RC(RTFileClose(hFile1), VINF_SUCCESS); 2424 RTTESTI_CHECK_RC(RTFileClose(hFileNoCache), VINF_SUCCESS); 2462 if (hFileNoCache != NIL_RTFILE || !g_fIgnoreNoCache) 2463 RTTESTI_CHECK_RC(RTFileClose(hFileNoCache), VINF_SUCCESS); 2425 2464 RTTESTI_CHECK_RC(RTFileClose(hFileWriteThru), VINF_SUCCESS); 2426 2465 RTTESTI_CHECK_RC(RTFileDelete(g_szDir), VINF_SUCCESS); … … 2428 2467 2429 2468 2469 /** 2470 * Display the usage to @a pStrm. 2471 */ 2430 2472 static void Usage(PRTSTREAM pStrm) 2431 2473 { … … 2442 2484 switch (g_aCmdOptions[i].iShort) 2443 2485 { 2444 case 'd': pszHelp = "The directory to use for testing. Default: CWD/fstestdir"; break; 2445 case 'e': pszHelp = "Enables all tests. Default: -e"; break; 2446 case 'z': pszHelp = "Disables all tests. Default: -e"; break; 2447 case 's': pszHelp = "Set benchmark duration in seconds. Default: 10 sec"; break; 2448 case 'm': pszHelp = "Set benchmark duration in milliseconds. Default: 10000 ms"; break; 2449 case 'v': pszHelp = "More verbose execution."; break; 2450 case 'q': pszHelp = "Quiet execution."; break; 2451 case 'h': pszHelp = "Displays this help and exit"; break; 2452 case 'V': pszHelp = "Displays the program revision"; break; 2453 case kCmdOpt_ShowDuration: pszHelp = "Show duration of profile runs. default: --no-show-duration"; break; 2454 case kCmdOpt_NoShowDuration: pszHelp = "Hide duration of profile runs. default: --no-show-duration"; break; 2455 case kCmdOpt_ShowIterations: pszHelp = "Show iteration count for profile runs. default: --no-show-iterations"; break; 2456 case kCmdOpt_NoShowIterations: pszHelp = "Hide iteration count for profile runs. default: --no-show-iterations"; break; 2486 case 'd': pszHelp = "The directory to use for testing. default: CWD/fstestdir"; break; 2487 case 'e': pszHelp = "Enables all tests. default: -e"; break; 2488 case 'z': pszHelp = "Disables all tests. default: -e"; break; 2489 case 's': pszHelp = "Set benchmark duration in seconds. default: 10 sec"; break; 2490 case 'm': pszHelp = "Set benchmark duration in milliseconds. default: 10000 ms"; break; 2491 case 'v': pszHelp = "More verbose execution."; break; 2492 case 'q': pszHelp = "Quiet execution."; break; 2493 case 'h': pszHelp = "Displays this help and exit"; break; 2494 case 'V': pszHelp = "Displays the program revision"; break; 2495 case kCmdOpt_ShowDuration: pszHelp = "Show duration of profile runs. default: --no-show-duration"; break; 2496 case kCmdOpt_NoShowDuration: pszHelp = "Hide duration of profile runs. default: --no-show-duration"; break; 2497 case kCmdOpt_ShowIterations: pszHelp = "Show iteration count for profile runs. default: --no-show-iterations"; break; 2498 case kCmdOpt_NoShowIterations: pszHelp = "Hide iteration count for profile runs. default: --no-show-iterations"; break; 2499 case kCmdOpt_ManyFiles: pszHelp = "Count of files in big test dir. default: --many-files 10000"; break; 2500 case kCmdOpt_NoManyFiles: pszHelp = "Skip big test dir with many files. default: --many-files 10000"; break; 2501 case kCmdOpt_ManyTreeFilesPerDir: pszHelp = "Count of files per directory in test tree. default: 640"; break; 2502 case kCmdOpt_ManyTreeSubdirsPerDir: pszHelp = "Count of subdirs per directory in test tree. default: 16"; break; 2503 case kCmdOpt_ManyTreeDepth: pszHelp = "Depth of test tree (not counting root). default: 1"; break; 2504 case kCmdOpt_IgnoreNoCache: pszHelp = "Ignore error wrt no-cache handle. default: --no-ignore-no-cache"; break; 2505 case kCmdOpt_NoIgnoreNoCache: pszHelp = "Do not ignore error wrt no-cache handle. default: --no-ignore-no-cache"; break; 2506 case kCmdOpt_IoFileSize: pszHelp = "Size of file used for I/O tests. default: 512 MB"; break; 2507 case kCmdOpt_SetBlockSize: pszHelp = "Sets single I/O block size (in bytes)."; break; 2508 case kCmdOpt_AddBlockSize: pszHelp = "Adds an I/O block size (in bytes)."; break; 2457 2509 default: 2458 2510 if (g_aCmdOptions[i].iShort >= kCmdOpt_First) … … 2472 2524 char szOpt[64]; 2473 2525 RTStrPrintf(szOpt, sizeof(szOpt), "%s, -%c", g_aCmdOptions[i].pszLong, g_aCmdOptions[i].iShort); 2474 RTStrmPrintf(pStrm, " %- 20s%s\n", szOpt, pszHelp);2526 RTStrmPrintf(pStrm, " %-19s %s\n", szOpt, pszHelp); 2475 2527 } 2476 2528 else 2477 RTStrmPrintf(pStrm, " %-20s%s\n", g_aCmdOptions[i].pszLong, pszHelp); 2478 } 2529 RTStrmPrintf(pStrm, " %-19s %s\n", g_aCmdOptions[i].pszLong, pszHelp); 2530 } 2531 } 2532 2533 2534 static uint32_t fsPerfCalcManyTreeFiles(void) 2535 { 2536 uint32_t cDirs = 1; 2537 for (uint32_t i = 0, cDirsAtLevel = 1; i < g_cManyTreeDepth; i++) 2538 { 2539 cDirs += cDirsAtLevel * g_cManyTreeSubdirsPerDir; 2540 cDirsAtLevel *= g_cManyTreeSubdirsPerDir; 2541 } 2542 return g_cManyTreeFilesPerDir * cDirs; 2479 2543 } 2480 2544 … … 2586 2650 case RT_CONCAT(kCmdOpt_,a_Stem): RT_CONCAT(g_f,a_Stem) = true; break; \ 2587 2651 case RT_CONCAT(kCmdOpt_No,a_Stem): RT_CONCAT(g_f,a_Stem) = false; break 2588 CASE_OPT(ManyFiles);2589 2652 CASE_OPT(Open); 2590 2653 CASE_OPT(FStat); … … 2605 2668 CASE_OPT(FSync); 2606 2669 CASE_OPT(MMap); 2670 CASE_OPT(IgnoreNoCache); 2607 2671 2608 2672 CASE_OPT(ShowDuration); 2609 2673 CASE_OPT(ShowIterations); 2610 2674 #undef CASE_OPT 2675 2676 case kCmdOpt_ManyFiles: 2677 g_fManyFiles = ValueUnion.u32 > 0; 2678 g_cManyFiles = ValueUnion.u32; 2679 break; 2680 2681 case kCmdOpt_NoManyFiles: 2682 g_fManyFiles = false; 2683 break; 2684 2685 case kCmdOpt_ManyTreeFilesPerDir: 2686 if (ValueUnion.u32 > 0 && ValueUnion.u32 <= _64M) 2687 { 2688 g_cManyTreeFilesPerDir = ValueUnion.u32; 2689 g_cManyTreeFiles = fsPerfCalcManyTreeFiles(); 2690 break; 2691 } 2692 RTTestFailed(g_hTest, "Out of range --files-per-dir value: %u (%#x)\n", ValueUnion.u32, ValueUnion.u32); 2693 return RTTestSummaryAndDestroy(g_hTest); 2694 2695 case kCmdOpt_ManyTreeSubdirsPerDir: 2696 if (ValueUnion.u32 > 0 && ValueUnion.u32 <= 1024) 2697 { 2698 g_cManyTreeSubdirsPerDir = ValueUnion.u32; 2699 g_cManyTreeFiles = fsPerfCalcManyTreeFiles(); 2700 break; 2701 } 2702 RTTestFailed(g_hTest, "Out of range --subdirs-per-dir value: %u (%#x)\n", ValueUnion.u32, ValueUnion.u32); 2703 return RTTestSummaryAndDestroy(g_hTest); 2704 2705 case kCmdOpt_ManyTreeDepth: 2706 if (ValueUnion.u32 <= 8) 2707 { 2708 g_cManyTreeDepth = ValueUnion.u32; 2709 g_cManyTreeFiles = fsPerfCalcManyTreeFiles(); 2710 break; 2711 } 2712 RTTestFailed(g_hTest, "Out of range --tree-depth value: %u (%#x)\n", ValueUnion.u32, ValueUnion.u32); 2713 return RTTestSummaryAndDestroy(g_hTest); 2714 2715 case kCmdOpt_IoFileSize: 2716 if (ValueUnion.u64 == 0) 2717 g_cbIoFile = _512M; 2718 else 2719 g_cbIoFile = ValueUnion.u64; 2720 break; 2721 2722 case kCmdOpt_SetBlockSize: 2723 if (ValueUnion.u32 > 0) 2724 { 2725 g_cIoBlocks = 1; 2726 g_acbIoBlocks[0] = ValueUnion.u32; 2727 } 2728 else 2729 { 2730 RTTestFailed(g_hTest, "Invalid I/O block size: %u (%#x)\n", ValueUnion.u32, ValueUnion.u32); 2731 return RTTestSummaryAndDestroy(g_hTest); 2732 } 2733 break; 2734 2735 case kCmdOpt_AddBlockSize: 2736 if (g_cIoBlocks >= RT_ELEMENTS(g_acbIoBlocks)) 2737 RTTestFailed(g_hTest, "Too many I/O block sizes: max %u\n", RT_ELEMENTS(g_acbIoBlocks)); 2738 else if (ValueUnion.u32 == 0) 2739 RTTestFailed(g_hTest, "Invalid I/O block size: %u (%#x)\n", ValueUnion.u32, ValueUnion.u32); 2740 else 2741 { 2742 g_acbIoBlocks[g_cIoBlocks++] = ValueUnion.u32; 2743 break; 2744 } 2745 return RTTestSummaryAndDestroy(g_hTest); 2611 2746 2612 2747 case 'q':
Note:
See TracChangeset
for help on using the changeset viewer.