- Timestamp:
- Mar 27, 2019 11:42:19 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/fs/FsPerf.cpp
r77925 r77926 47 47 #include <iprt/param.h> 48 48 #include <iprt/path.h> 49 #ifdef RT_OS_LINUX 50 # include <iprt/pipe.h> 51 #endif 49 52 #include <iprt/process.h> 50 53 #include <iprt/rand.h> … … 73 76 # ifdef RT_OS_LINUX 74 77 # include <sys/sendfile.h> 78 # include <sys/syscall.h> 75 79 # endif 76 80 #endif … … 278 282 kCmdOpt_SendFile, 279 283 kCmdOpt_NoSendFile, 284 #ifdef RT_OS_LINUX 285 kCmdOpt_Splice, 286 kCmdOpt_NoSplice, 287 #endif 280 288 kCmdOpt_WritePerf, 281 289 kCmdOpt_NoWritePerf, … … 362 370 { "--sendfile", kCmdOpt_SendFile, RTGETOPT_REQ_NOTHING }, 363 371 { "--no-sendfile", kCmdOpt_NoSendFile, RTGETOPT_REQ_NOTHING }, 372 #ifdef RT_OS_LINUX 373 { "--splice", kCmdOpt_Splice, RTGETOPT_REQ_NOTHING }, 374 { "--no-splice", kCmdOpt_NoSplice, RTGETOPT_REQ_NOTHING }, 375 #endif 364 376 { "--write-tests", kCmdOpt_WriteTests, RTGETOPT_REQ_NOTHING }, 365 377 { "--no-write-tests", kCmdOpt_NoWriteTests, RTGETOPT_REQ_NOTHING }, … … 425 437 static bool g_fReadPerf = true; 426 438 static bool g_fSendFile = true; 439 #ifdef RT_OS_LINUX 440 static bool g_fSplice = true; 441 #endif 427 442 static bool g_fWriteTests= true; 428 443 static bool g_fWritePerf = true; … … 1918 1933 } 1919 1934 1920 #ifdef RT_OS_LINUX 1935 #if defined(RT_OS_LINUX) 1936 1921 1937 /** 1922 1938 * Send file thread arguments. … … 1940 1956 FSPERFSENDFILEARGS *pArgs = (FSPERFSENDFILEARGS *)pvUser; 1941 1957 int rc = VINF_SUCCESS; 1958 1959 if (pArgs->fCheckBuf) 1960 RTTestSetDefault(g_hTest, NULL); 1942 1961 1943 1962 uint64_t cbReceived = 0; … … 2054 2073 */ 2055 2074 FSPERFSENDFILEARGS Args; 2056 Args.cbBuf = _16M;2075 Args.cbBuf = RT_MIN(cbFileMax, _16M); 2057 2076 Args.pbBuf = (uint8_t *)RTMemAlloc(Args.cbBuf); 2058 2077 while (!Args.pbBuf) … … 2128 2147 RTTestIValue("throughput", (uint64_t)(cbTotal / ((double)nsElapsed / RT_NS_1SEC)), RTTESTUNIT_BYTES_PER_SEC); 2129 2148 RTTestIValue("calls", cIterations, RTTESTUNIT_CALLS); 2149 RTTestIValue("bytes", cbTotal, RTTESTUNIT_BYTES); 2150 if (g_fShowDuration) 2151 RTTestIValue("duration", nsElapsed, RTTESTUNIT_NS); 2152 2153 /* 2154 * Cleanup. 2155 */ 2156 RTMemFree(Args.pbBuf); 2157 } 2158 2159 #endif /* RT_OS_LINUX */ 2160 #ifdef RT_OS_LINUX 2161 2162 /** 2163 * Send file thread arguments. 2164 */ 2165 typedef struct FSPERFSPLICEARGS 2166 { 2167 uint64_t offFile; 2168 size_t cbSend; 2169 uint64_t cbSent; 2170 size_t cbBuf; 2171 uint8_t *pbBuf; 2172 uint8_t bFiller; 2173 bool fCheckBuf; 2174 uint32_t cCalls; 2175 RTPIPE hPipe; 2176 uint64_t volatile tsThreadDone; 2177 } FSPERFSPLICEARGS; 2178 2179 2180 /** Thread receiving the bytes from a splice() call. */ 2181 static DECLCALLBACK(int) fsPerfSpliceRecvThread(RTTHREAD hSelf, void *pvUser) 2182 { 2183 FSPERFSPLICEARGS *pArgs = (FSPERFSPLICEARGS *)pvUser; 2184 int rc = VINF_SUCCESS; 2185 2186 if (pArgs->fCheckBuf) 2187 RTTestSetDefault(g_hTest, NULL); 2188 2189 uint64_t cbReceived = 0; 2190 while (cbReceived < pArgs->cbSent) 2191 { 2192 size_t const cbToRead = RT_MIN(pArgs->cbBuf, pArgs->cbSent - cbReceived); 2193 size_t cbActual = 0; 2194 RTTEST_CHECK_RC_BREAK(g_hTest, rc = RTPipeReadBlocking(pArgs->hPipe, pArgs->pbBuf, cbToRead, &cbActual), VINF_SUCCESS); 2195 RTTEST_CHECK_BREAK(g_hTest, cbActual != 0); 2196 RTTEST_CHECK(g_hTest, cbActual <= cbToRead); 2197 if (pArgs->fCheckBuf) 2198 fsPerfCheckReadBuf(__LINE__, pArgs->offFile + cbReceived, pArgs->pbBuf, cbActual, pArgs->bFiller); 2199 cbReceived += cbActual; 2200 } 2201 2202 pArgs->tsThreadDone = RTTimeNanoTS(); 2203 2204 if (cbReceived == pArgs->cbSent && RT_SUCCESS(rc)) 2205 { 2206 size_t cbActual = 0; 2207 rc = RTPipeRead(pArgs->hPipe, pArgs->pbBuf, 1, &cbActual); 2208 if (rc != VINF_SUCCESS && rc != VINF_TRY_AGAIN && rc != VERR_BROKEN_PIPE) 2209 RTTestFailed(g_hTest, "RTPipeReadBlocking() -> %Rrc; expected VINF_SUCCESS or VINF_TRY_AGAIN\n", rc); 2210 else if (cbActual != 0) 2211 RTTestFailed(g_hTest, "splice read pipe still contains data when done!\n"); 2212 } 2213 2214 RTTEST_CHECK_RC(g_hTest, RTPipeClose(pArgs->hPipe), VINF_SUCCESS); 2215 pArgs->hPipe = NIL_RTPIPE; 2216 2217 RT_NOREF(hSelf); 2218 return rc; 2219 } 2220 2221 2222 /** Sends hFile1 to a pipe via the Linux-specific splice() syscall. */ 2223 static uint64_t fsPerfSpliceSendFile(FSPERFSPLICEARGS *pArgs, RTFILE hFile1, uint64_t offFile, 2224 size_t cbSend, uint64_t cbSent, uint8_t bFiller, bool fCheckBuf, unsigned iLine) 2225 { 2226 /* Copy parameters to the argument structure: */ 2227 pArgs->offFile = offFile; 2228 pArgs->cbSend = cbSend; 2229 pArgs->cbSent = cbSent; 2230 pArgs->bFiller = bFiller; 2231 pArgs->fCheckBuf = fCheckBuf; 2232 2233 /* Create a socket pair. */ 2234 pArgs->hPipe = NIL_RTPIPE; 2235 RTPIPE hPipeW = NIL_RTPIPE; 2236 RTTESTI_CHECK_RC_RET(RTPipeCreate(&pArgs->hPipe, &hPipeW, 0 /*fFlags*/), VINF_SUCCESS, 0); 2237 2238 /* Create the receiving thread: */ 2239 int rc; 2240 RTTHREAD hThread = NIL_RTTHREAD; 2241 RTTESTI_CHECK_RC(rc = RTThreadCreate(&hThread, fsPerfSpliceRecvThread, pArgs, 0, 2242 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "splicerecv"), VINF_SUCCESS); 2243 if (RT_SUCCESS(rc)) 2244 { 2245 uint64_t const tsStart = RTTimeNanoTS(); 2246 size_t cbLeft = cbSend; 2247 size_t cbTotal = 0; 2248 do 2249 { 2250 loff_t offFileIn = offFile; 2251 ssize_t cbActual = splice((int)RTFileToNative(hFile1), &offFileIn, (int)RTPipeToNative(hPipeW), NULL, 2252 cbLeft, 0 /*fFlags*/); 2253 int const iErr = errno; 2254 if (RT_UNLIKELY(cbActual < 0)) 2255 { 2256 RTTestIFailed("%u: splice(file, &%#RX64, pipe, NULL, %#zx, 0) failed (%zd): %d (%Rrc), offFileIn=%#RX64\n", 2257 iLine, offFile, cbLeft, cbActual, iErr, RTErrConvertFromErrno(iErr), (uint64_t)offFileIn); 2258 break; 2259 } 2260 RTTESTI_CHECK_BREAK((uint64_t)cbActual <= cbLeft); 2261 if ((uint64_t)offFileIn != offFile + (uint64_t)cbActual) 2262 { 2263 RTTestIFailed("%u: splice(file, &%#RX64, pipe, NULL, %#zx, 0): %#zx; offFileIn=%#RX64, expected %#RX64\n", 2264 iLine, offFile, cbLeft, cbActual, (uint64_t)offFileIn, offFile + (uint64_t)cbActual); 2265 break; 2266 } 2267 if (cbActual > 0) 2268 { 2269 pArgs->cCalls++; 2270 offFile += (size_t)cbActual; 2271 cbTotal += (size_t)cbActual; 2272 cbLeft -= (size_t)cbActual; 2273 } 2274 else 2275 break; 2276 } while (cbLeft > 0); 2277 2278 if (cbTotal != pArgs->cbSent) 2279 RTTestIFailed("%u: spliced a total of %#zx bytes, expected %#zx!\n", iLine, cbTotal, pArgs->cbSent); 2280 2281 RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); 2282 RTTESTI_CHECK_RC(RTThreadWait(hThread, 30 * RT_NS_1SEC, NULL), VINF_SUCCESS); 2283 2284 if (pArgs->tsThreadDone >= tsStart) 2285 return RT_MAX(pArgs->tsThreadDone - tsStart, 1); 2286 } 2287 return 0; 2288 } 2289 2290 2291 static void fsPerfSpliceToPipe(RTFILE hFile1, uint64_t cbFile) 2292 { 2293 RTTestISub("splice/to-pipe"); 2294 2295 /* 2296 * splice was introduced in 2.6.17 according to the man-page. 2297 */ 2298 char szRelease[64]; 2299 RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szRelease, sizeof(szRelease)); 2300 if (RTStrVersionCompare(szRelease, "2.6.17") < 0) 2301 { 2302 RTTestPassed(g_hTest, "too old kernel (%s)", szRelease); 2303 return; 2304 } 2305 2306 uint64_t const cbFileMax = RT_MIN(cbFile, UINT32_MAX - PAGE_OFFSET_MASK); 2307 signal(SIGPIPE, SIG_IGN); 2308 2309 /* 2310 * Allocate a buffer. 2311 */ 2312 FSPERFSPLICEARGS Args; 2313 Args.cbBuf = RT_MIN(cbFileMax, _16M); 2314 Args.pbBuf = (uint8_t *)RTMemAlloc(Args.cbBuf); 2315 while (!Args.pbBuf) 2316 { 2317 Args.cbBuf /= 8; 2318 RTTESTI_CHECK_RETV(Args.cbBuf >= _64K); 2319 Args.pbBuf = (uint8_t *)RTMemAlloc(Args.cbBuf); 2320 } 2321 2322 /* 2323 * First iteration with default buffer content. 2324 */ 2325 fsPerfSpliceSendFile(&Args, hFile1, 0, cbFileMax, cbFileMax, 0xf6, true /*fCheckBuf*/, __LINE__); 2326 if (cbFileMax == cbFile) 2327 fsPerfSpliceSendFile(&Args, hFile1, 63, cbFileMax, cbFileMax - 63, 0xf6, true /*fCheckBuf*/, __LINE__); 2328 else 2329 fsPerfSpliceSendFile(&Args, hFile1, 63, cbFileMax - 63, cbFileMax - 63, 0xf6, true /*fCheckBuf*/, __LINE__); 2330 2331 /* 2332 * Write a block using the regular API and then send it, checking that 2333 * the any caching that sendfile does is correctly updated. 2334 */ 2335 uint8_t bFiller = 0xf6; 2336 size_t cbToSend = RT_MIN(cbFileMax, Args.cbBuf); 2337 do 2338 { 2339 fsPerfSpliceSendFile(&Args, hFile1, 0, cbToSend, cbToSend, bFiller, true /*fCheckBuf*/, __LINE__); /* prime cache */ 2340 2341 bFiller += 1; 2342 fsPerfFillWriteBuf(0, Args.pbBuf, cbToSend, bFiller); 2343 RTTESTI_CHECK_RC(RTFileWriteAt(hFile1, 0, Args.pbBuf, cbToSend, NULL), VINF_SUCCESS); 2344 2345 fsPerfSpliceSendFile(&Args, hFile1, 0, cbToSend, cbToSend, bFiller, true /*fCheckBuf*/, __LINE__); 2346 2347 cbToSend /= 2; 2348 } while (cbToSend >= PAGE_SIZE && ((unsigned)bFiller - 0xf7U) < 64); 2349 2350 /* 2351 * Restore buffer content 2352 */ 2353 bFiller = 0xf6; 2354 fsPerfFillWriteBuf(0, Args.pbBuf, Args.cbBuf, bFiller); 2355 RTTESTI_CHECK_RC(RTFileWriteAt(hFile1, 0, Args.pbBuf, Args.cbBuf, NULL), VINF_SUCCESS); 2356 2357 /* 2358 * Do 128 random sends. 2359 */ 2360 uint64_t const cbSmall = RT_MIN(_256K, cbFileMax / 16); 2361 for (uint32_t iTest = 0; iTest < 128; iTest++) 2362 { 2363 cbToSend = (size_t)RTRandU64Ex(1, iTest < 64 ? cbSmall : cbFileMax); 2364 uint64_t const offToSendFrom = RTRandU64Ex(0, cbFile - 1); 2365 uint64_t const cbSent = offToSendFrom + cbToSend <= cbFile ? cbToSend : cbFile - offToSendFrom; 2366 2367 fsPerfSpliceSendFile(&Args, hFile1, offToSendFrom, cbToSend, cbSent, bFiller, true /*fCheckBuf*/, __LINE__); 2368 } 2369 2370 /* 2371 * Benchmark it. 2372 */ 2373 Args.cCalls = 0; 2374 uint32_t cIterations = 0; 2375 uint64_t nsElapsed = 0; 2376 for (;;) 2377 { 2378 uint64_t cNsThis = fsPerfSpliceSendFile(&Args, hFile1, 0, cbFileMax, cbFileMax, 0xf6, false /*fCheckBuf*/, __LINE__); 2379 nsElapsed += cNsThis; 2380 cIterations++; 2381 if (!cNsThis || nsElapsed >= g_nsTestRun) 2382 break; 2383 } 2384 uint64_t cbTotal = cbFileMax * cIterations; 2385 RTTestIValue("latency", nsElapsed / Args.cCalls, RTTESTUNIT_NS_PER_CALL); 2386 RTTestIValue("throughput", (uint64_t)(cbTotal / ((double)nsElapsed / RT_NS_1SEC)), RTTESTUNIT_BYTES_PER_SEC); 2387 RTTestIValue("calls", Args.cCalls, RTTESTUNIT_CALLS); 2388 RTTestIValue("bytes/call", cbTotal / Args.cCalls, RTTESTUNIT_BYTES); 2389 RTTestIValue("iterations", cIterations, RTTESTUNIT_NONE); 2390 RTTestIValue("bytes", cbTotal, RTTESTUNIT_BYTES); 2391 if (g_fShowDuration) 2392 RTTestIValue("duration", nsElapsed, RTTESTUNIT_NS); 2393 2394 /* 2395 * Cleanup. 2396 */ 2397 RTMemFree(Args.pbBuf); 2398 } 2399 2400 2401 /** Thread sending the bytes to a splice() call. */ 2402 static DECLCALLBACK(int) fsPerfSpliceSendThread(RTTHREAD hSelf, void *pvUser) 2403 { 2404 FSPERFSPLICEARGS *pArgs = (FSPERFSPLICEARGS *)pvUser; 2405 int rc = VINF_SUCCESS; 2406 2407 uint64_t offFile = pArgs->offFile; 2408 uint64_t cbTotalSent = 0; 2409 while (cbTotalSent < pArgs->cbSent) 2410 { 2411 size_t const cbToSend = RT_MIN(pArgs->cbBuf, pArgs->cbSent - cbTotalSent); 2412 fsPerfFillWriteBuf(offFile, pArgs->pbBuf, cbToSend, pArgs->bFiller); 2413 RTTEST_CHECK_RC_BREAK(g_hTest, rc = RTPipeWriteBlocking(pArgs->hPipe, pArgs->pbBuf, cbToSend, NULL), VINF_SUCCESS); 2414 offFile += cbToSend; 2415 cbTotalSent += cbToSend; 2416 } 2417 2418 pArgs->tsThreadDone = RTTimeNanoTS(); 2419 2420 RTTEST_CHECK_RC(g_hTest, RTPipeClose(pArgs->hPipe), VINF_SUCCESS); 2421 pArgs->hPipe = NIL_RTPIPE; 2422 2423 RT_NOREF(hSelf); 2424 return rc; 2425 } 2426 2427 2428 /** Fill hFile1 via a pipe and the Linux-specific splice() syscall. */ 2429 static uint64_t fsPerfSpliceWriteFile(FSPERFSPLICEARGS *pArgs, RTFILE hFile1, uint64_t offFile, 2430 size_t cbSend, uint64_t cbSent, uint8_t bFiller, bool fCheckFile, unsigned iLine) 2431 { 2432 /* Copy parameters to the argument structure: */ 2433 pArgs->offFile = offFile; 2434 pArgs->cbSend = cbSend; 2435 pArgs->cbSent = cbSent; 2436 pArgs->bFiller = bFiller; 2437 pArgs->fCheckBuf = false; 2438 2439 /* Create a socket pair. */ 2440 pArgs->hPipe = NIL_RTPIPE; 2441 RTPIPE hPipeR = NIL_RTPIPE; 2442 RTTESTI_CHECK_RC_RET(RTPipeCreate(&hPipeR, &pArgs->hPipe, 0 /*fFlags*/), VINF_SUCCESS, 0); 2443 2444 /* Create the receiving thread: */ 2445 int rc; 2446 RTTHREAD hThread = NIL_RTTHREAD; 2447 RTTESTI_CHECK_RC(rc = RTThreadCreate(&hThread, fsPerfSpliceSendThread, pArgs, 0, 2448 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "splicerecv"), VINF_SUCCESS); 2449 if (RT_SUCCESS(rc)) 2450 { 2451 /* 2452 * Do the splicing. 2453 */ 2454 uint64_t const tsStart = RTTimeNanoTS(); 2455 size_t cbLeft = cbSend; 2456 size_t cbTotal = 0; 2457 do 2458 { 2459 loff_t offFileOut = offFile; 2460 ssize_t cbActual = splice((int)RTPipeToNative(hPipeR), NULL, (int)RTFileToNative(hFile1), &offFileOut, 2461 cbLeft, 0 /*fFlags*/); 2462 int const iErr = errno; 2463 if (RT_UNLIKELY(cbActual < 0)) 2464 { 2465 RTTestIFailed("%u: splice(pipe, NULL, file, &%#RX64, %#zx, 0) failed (%zd): %d (%Rrc), offFileOut=%#RX64\n", 2466 iLine, offFile, cbLeft, cbActual, iErr, RTErrConvertFromErrno(iErr), (uint64_t)offFileOut); 2467 break; 2468 } 2469 RTTESTI_CHECK_BREAK((uint64_t)cbActual <= cbLeft); 2470 if ((uint64_t)offFileOut != offFile + (uint64_t)cbActual) 2471 { 2472 RTTestIFailed("%u: splice(pipe, NULL, file, &%#RX64, %#zx, 0): %#zx; offFileOut=%#RX64, expected %#RX64\n", 2473 iLine, offFile, cbLeft, cbActual, (uint64_t)offFileOut, offFile + (uint64_t)cbActual); 2474 break; 2475 } 2476 if (cbActual > 0) 2477 { 2478 pArgs->cCalls++; 2479 offFile += (size_t)cbActual; 2480 cbTotal += (size_t)cbActual; 2481 cbLeft -= (size_t)cbActual; 2482 } 2483 else 2484 break; 2485 } while (cbLeft > 0); 2486 uint64_t const nsElapsed = RTTimeNanoTS() - tsStart; 2487 2488 if (cbTotal != pArgs->cbSent) 2489 RTTestIFailed("%u: spliced a total of %#zx bytes, expected %#zx!\n", iLine, cbTotal, pArgs->cbSent); 2490 2491 RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); 2492 RTTESTI_CHECK_RC(RTThreadWait(hThread, 30 * RT_NS_1SEC, NULL), VINF_SUCCESS); 2493 2494 /* Check the file content. */ 2495 if (fCheckFile && cbTotal == pArgs->cbSent) 2496 { 2497 offFile = pArgs->offFile; 2498 cbLeft = cbSent; 2499 while (cbLeft > 0) 2500 { 2501 size_t cbToRead = RT_MIN(cbLeft, pArgs->cbBuf); 2502 RTTESTI_CHECK_RC_BREAK(RTFileReadAt(hFile1, offFile, pArgs->pbBuf, cbToRead, NULL), VINF_SUCCESS); 2503 if (!fsPerfCheckReadBuf(iLine, offFile, pArgs->pbBuf, cbToRead, pArgs->bFiller)) 2504 break; 2505 offFile += cbToRead; 2506 cbLeft -= cbToRead; 2507 } 2508 } 2509 return nsElapsed; 2510 } 2511 return 0; 2512 } 2513 2514 2515 static void fsPerfSpliceToFile(RTFILE hFile1, uint64_t cbFile) 2516 { 2517 RTTestISub("splice/to-file"); 2518 2519 /* 2520 * splice was introduced in 2.6.17 according to the man-page. 2521 */ 2522 char szRelease[64]; 2523 RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szRelease, sizeof(szRelease)); 2524 if (RTStrVersionCompare(szRelease, "2.6.17") < 0) 2525 { 2526 RTTestPassed(g_hTest, "too old kernel (%s)", szRelease); 2527 return; 2528 } 2529 2530 uint64_t const cbFileMax = RT_MIN(cbFile, UINT32_MAX - PAGE_OFFSET_MASK); 2531 signal(SIGPIPE, SIG_IGN); 2532 2533 /* 2534 * Allocate a buffer. 2535 */ 2536 FSPERFSPLICEARGS Args; 2537 Args.cbBuf = RT_MIN(cbFileMax, _16M); 2538 Args.pbBuf = (uint8_t *)RTMemAlloc(Args.cbBuf); 2539 while (!Args.pbBuf) 2540 { 2541 Args.cbBuf /= 8; 2542 RTTESTI_CHECK_RETV(Args.cbBuf >= _64K); 2543 Args.pbBuf = (uint8_t *)RTMemAlloc(Args.cbBuf); 2544 } 2545 2546 /* 2547 * Do the whole file. 2548 */ 2549 uint8_t bFiller = 0x76; 2550 fsPerfSpliceWriteFile(&Args, hFile1, 0, cbFileMax, cbFileMax, bFiller, true /*fCheckFile*/, __LINE__); 2551 2552 /* 2553 * Do 64 random chunks (this is slower). 2554 */ 2555 uint64_t const cbSmall = RT_MIN(_256K, cbFileMax / 16); 2556 for (uint32_t iTest = 0; iTest < 64; iTest++) 2557 { 2558 size_t const cbToWrite = (size_t)RTRandU64Ex(1, iTest < 24 ? cbSmall : cbFileMax); 2559 uint64_t const offToWriteAt = RTRandU64Ex(0, cbFile - cbToWrite); 2560 uint64_t const cbTryRead = cbToWrite + (iTest & 1 ? RTRandU32Ex(0, _64K) : 0); 2561 2562 bFiller++; 2563 fsPerfSpliceWriteFile(&Args, hFile1, offToWriteAt, cbTryRead, cbToWrite, bFiller, true /*fCheckFile*/, __LINE__); 2564 } 2565 2566 /* 2567 * Benchmark it. 2568 */ 2569 Args.cCalls = 0; 2570 uint32_t cIterations = 0; 2571 uint64_t nsElapsed = 0; 2572 for (;;) 2573 { 2574 uint64_t cNsThis = fsPerfSpliceWriteFile(&Args, hFile1, 0, cbFileMax, cbFileMax, 0xf6, false /*fCheckBuf*/, __LINE__); 2575 nsElapsed += cNsThis; 2576 cIterations++; 2577 if (!cNsThis || nsElapsed >= g_nsTestRun) 2578 break; 2579 } 2580 uint64_t cbTotal = cbFileMax * cIterations; 2581 RTTestIValue("latency", nsElapsed / Args.cCalls, RTTESTUNIT_NS_PER_CALL); 2582 RTTestIValue("throughput", (uint64_t)(cbTotal / ((double)nsElapsed / RT_NS_1SEC)), RTTESTUNIT_BYTES_PER_SEC); 2583 RTTestIValue("calls", Args.cCalls, RTTESTUNIT_CALLS); 2584 RTTestIValue("bytes/call", cbTotal / Args.cCalls, RTTESTUNIT_BYTES); 2585 RTTestIValue("iterations", cIterations, RTTESTUNIT_NONE); 2130 2586 RTTestIValue("bytes", cbTotal, RTTESTUNIT_BYTES); 2131 2587 if (g_fShowDuration) … … 3444 3900 for (unsigned i = 0; i < g_cIoBlocks; i++) 3445 3901 fsPerfIoReadBlockSize(hFile1, cbFile, g_acbIoBlocks[i]); 3446 3447 #ifdef RT_OS_LINUX 3902 #if defined(RT_OS_LINUX) 3448 3903 if (g_fSendFile) 3449 3904 fsPerfSendFile(hFile1, cbFile); 3450 3905 #endif 3451 3906 #ifdef RT_OS_LINUX 3452 //if (g_fSplice)3453 // fsPerfSpliceOut(hFile1, cbFile);3907 if (g_fSplice) 3908 fsPerfSpliceToPipe(hFile1, cbFile); 3454 3909 #endif 3455 3456 3910 if (g_fMMap) 3457 3911 fsPerfMMap(hFile1, hFileNoCache, cbFile); … … 3463 3917 for (unsigned i = 0; i < g_cIoBlocks; i++) 3464 3918 fsPerfIoWriteBlockSize(hFile1, cbFile, g_acbIoBlocks[i]); 3465 3919 #ifdef RT_OS_LINUX 3920 if (g_fSplice) 3921 fsPerfSpliceToFile(hFile1, cbFile); 3922 #endif 3466 3923 if (g_fFSync) 3467 3924 fsPerfFSync(hFile1, cbFile); … … 3924 4381 g_fReadPerf = true; 3925 4382 g_fSendFile = true; 4383 #ifdef RT_OS_LINUX 4384 g_fSplice = true; 4385 #endif 3926 4386 g_fWriteTests= true; 3927 4387 g_fWritePerf = true; … … 3951 4411 g_fReadPerf = false; 3952 4412 g_fSendFile = false; 4413 #ifdef RT_OS_LINUX 4414 g_fSplice = false; 4415 #endif 3953 4416 g_fWriteTests= false; 3954 4417 g_fWritePerf = false; … … 3979 4442 CASE_OPT(ReadPerf); 3980 4443 CASE_OPT(SendFile); 4444 #ifdef RT_OS_LINUX 4445 CASE_OPT(Splice); 4446 #endif 3981 4447 CASE_OPT(WriteTests); 3982 4448 CASE_OPT(WritePerf); … … 4138 4604 fsPerfChSize(); 4139 4605 if ( g_fReadPerf || g_fReadTests || g_fSendFile || g_fWritePerf || g_fWriteTests 4606 #ifdef RT_OS_LINUX 4607 || g_fSplice 4608 #endif 4140 4609 || g_fSeek || g_fFSync || g_fMMap) 4141 4610 fsPerfIo();
Note:
See TracChangeset
for help on using the changeset viewer.