Changeset 76897 in vbox for trunk/src/VBox/ValidationKit
- Timestamp:
- Jan 19, 2019 6:56:27 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 128265
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/fs/FsPerf.cpp
r76889 r76897 62 62 do { \ 63 63 /* 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 \ 66 74 { \ 67 75 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++; \ 72 88 \ 73 89 /* Do the actual profiling: */ \ 74 90 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); \ 82 99 } while (0) 83 100 … … 94 111 \ 95 112 /* 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 \ 97 121 PFSPERFNAMEENTRY pCur; \ 98 for (uint32_t iIteration = 0; iIteration < (a_cEstimationIterations); iIteration++) \ 122 uint64_t iIteration = 0; \ 123 do \ 99 124 { \ 100 125 RTListForEach(&g_ManyTreeHead, pCur, FSPERFNAMEENTRY, Entry) \ … … 107 132 } \ 108 133 } \ 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 \ 112 147 /* Do the actual profiling: */ \ 113 148 fsPerfYield(); \ 114 uint32_t 115 uint64_t constnsStart = RTTimeNanoTS(); \116 for ( uint32_tiIteration = 0; iIteration < cIterations; iIteration++) \149 uint32_t cCalls = 0; \ 150 nsStart = RTTimeNanoTS(); \ 151 for (iIteration = 0; iIteration < cIterations; iIteration++) \ 117 152 { \ 118 153 RTListForEach(&g_ManyTreeHead, pCur, FSPERFNAMEENTRY, Entry) \ … … 127 162 } \ 128 163 } \ 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); \ 131 168 } while (0) 132 169 … … 273 310 * This is used for adjusting loop count estimates. */ 274 311 static 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. */ 314 static bool g_fShowDuration = true; 275 315 /** Verbosity level. */ 276 316 static uint32_t g_uVerbosity = 0; … … 298 338 299 339 /** The length of each test run. */ 300 static uint64_t g_nsTestRun = RT_NS_1SEC_64 * 10;340 static uint64_t g_nsTestRun = RT_NS_1SEC_64 * 10; 301 341 302 342 /** For the 'manyfiles' subdir. */ 303 static uint32_t g_cManyFiles = 10000;343 static uint32_t g_cManyFiles = 10000; 304 344 305 345 /** Number of files in the 'manytree' directory tree. */ 306 static uint32_t g_cManyTreeFiles = 640 + 16*640 /*10880*/;346 static uint32_t g_cManyTreeFiles = 640 + 16*640 /*10880*/; 307 347 /** Number of files per directory in the 'manytree' construct. */ 308 static uint32_t g_cManyTreeFilesPerDir = 640;348 static uint32_t g_cManyTreeFilesPerDir = 640; 309 349 /* Number of subdirs per directory in the 'manytree' construct. */ 310 static uint32_t g_cManyTreeSubdirsPerDir = 16;350 static uint32_t g_cManyTreeSubdirsPerDir = 16; 311 351 /** The depth of the 'manytree' directory tree. */ 312 static uint32_t g_cManyTreeDepth = 1;352 static uint32_t g_cManyTreeDepth = 1; 313 353 /** List of directories in the many tree, creation order. */ 314 354 static RTLISTANCHOR g_ManyTreeHead; 315 355 316 356 /** Number of configured I/O block sizes. */ 317 static uint32_t g_cIoBlocks = 8;357 static uint32_t g_cIoBlocks = 8; 318 358 /** Configured I/O block sizes. */ 319 static uint32_t g_acbIoBlocks[16] = { 1, 512, 4096, 16384, 65536, _1M, _32M, _128M };359 static uint32_t g_acbIoBlocks[16] = { 1, 512, 4096, 16384, 65536, _1M, _32M, _128M }; 320 360 /** The desired size of the test file we use for I/O. */ 321 static uint64_t g_cbIoFile = _512M;361 static uint64_t g_cbIoFile = _512M; 322 362 323 363 /** The length of g_szDir. */ … … 423 463 424 464 /** 465 * Prepares the test area. 466 * @returns VBox status code. 467 */ 468 static 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 /** 425 509 * Create a name list entry. 426 510 * @returns Pointer to the entry, NULL if out of memory. … … 460 544 return VINF_SUCCESS; 461 545 } 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 481 546 482 547 … … 545 610 546 611 612 DECL_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 621 DECL_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 547 630 void fsPerfOpen(void) 548 631 { … … 555 638 RTTESTI_CHECK_RC(RTFileOpen(&hFile, InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file")), 556 639 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); 557 642 558 643 /* … … 660 745 RTTESTI_CHECK_RC(RTPathQueryInfoEx(InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file")), 661 746 &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); 662 749 663 750 /* Shallow: */ … … 701 788 RTTESTI_CHECK_RC(RTPathSetMode(InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file")), 0665), 702 789 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); 703 791 704 792 /* Shallow: */ … … 746 834 NULL, &Time1, NULL, NULL, RTPATH_F_ON_LINK), 747 835 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); 748 839 749 840 /* Shallow: */ … … 813 904 RTTESTI_CHECK_RC(RTPathRename(InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file")), szPath, 0), 814 905 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); 815 908 816 909 RTFILE hFile1; … … 881 974 { 882 975 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); 883 982 884 983 /* 885 984 * The empty directory. 886 985 */ 887 RTDIR hDir;888 986 g_szEmptyDir[g_cchEmptyDir] = '\0'; 889 987 RTTESTI_CHECK_RC_RETV(RTDirOpen(&hDir, g_szEmptyDir), VINF_SUCCESS); … … 982 1080 RTTESTI_CHECK_RC(RTDirRemove(InEmptyDir(RT_STR_TUPLE("no-such-dir"))), VERR_FILE_NOT_FOUND); 983 1081 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); 984 1083 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); 985 1085 986 1086 /** @todo check what happens if non-final path component isn't a directory. unix … … 998 1098 RTTESTI_CHECK_RC(RTDirRemove(InDir(RT_STR_TUPLE("."))), VERR_INVALID_PARAMETER); /* EINVAL for '.' */ 999 1099 #endif 1100 #if defined(RT_OS_WINDOWS) 1101 RTTESTI_CHECK_RC(RTDirRemove(InDir(RT_STR_TUPLE(".."))), VERR_SHARING_VIOLATION); /* weird */ 1102 #else 1000 1103 RTTESTI_CHECK_RC(RTDirRemove(InDir(RT_STR_TUPLE(".."))), VERR_DIR_NOT_EMPTY); 1104 #endif 1001 1105 RTTESTI_CHECK_RC(RTDirRemove(InDir(RT_STR_TUPLE(""))), VERR_DIR_NOT_EMPTY); 1002 1106 … … 1087 1191 RTTESTI_CHECK_RC(RTFileDelete(InEmptyDir(RT_STR_TUPLE("no-such-file"))), VERR_FILE_NOT_FOUND); 1088 1192 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); 1089 1194 1090 1195 /* Directories: */ … … 1143 1248 * We need some free space to perform this test. 1144 1249 */ 1250 g_szDir[g_cchDir] = '\0'; 1145 1251 RTFOFF cbFree = 0; 1146 1252 RTTESTI_CHECK_RC_RETV(RTFsQuerySizes(g_szDir, NULL, &cbFree, NULL, NULL), VINF_SUCCESS); … … 1382 1488 1383 1489 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 1384 1551 DECL_FORCE_INLINE(int) fsPerfIoReadWorker(RTFILE hFile1, uint64_t cbFile, uint32_t cbBlock, uint8_t *pbBlock, 1385 1552 uint64_t *poffActual, uint32_t *pcSeeks) … … 1408 1575 1409 1576 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 { 1577 void 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 1417 1589 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 1593 DECL_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 1618 void 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"); 1474 1631 } 1475 1632 … … 1525 1682 fsPerfIoSeek(hFile1, cbFile); 1526 1683 if (g_fRead) 1684 { 1527 1685 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 } 1533 1688 if (g_fWrite) 1689 { 1534 1690 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 } 1540 1693 } 1541 1694 … … 1749 1902 { 1750 1903 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(); 1758 1905 if (RT_SUCCESS(rc)) 1759 1906 { 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(); 1812 1941 } 1813 1942
Note:
See TracChangeset
for help on using the changeset viewer.