Changeset 77831 in vbox for trunk/src/VBox/ValidationKit/utils/fs
- Timestamp:
- Mar 21, 2019 6:08:12 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/fs/FsPerf.cpp
r77692 r77831 284 284 kCmdOpt_SetBlockSize, 285 285 kCmdOpt_AddBlockSize, 286 kCmdOpt_Copy, 287 kCmdOpt_NoCopy, 286 288 287 289 kCmdOpt_ShowDuration, … … 364 366 { "--set-block-size", kCmdOpt_SetBlockSize, RTGETOPT_REQ_UINT32 }, 365 367 { "--add-block-size", kCmdOpt_AddBlockSize, RTGETOPT_REQ_UINT32 }, 368 { "--copy", kCmdOpt_Copy, RTGETOPT_REQ_NOTHING }, 369 { "--no-copy", kCmdOpt_NoCopy, RTGETOPT_REQ_NOTHING }, 366 370 367 371 { "--show-duration", kCmdOpt_ShowDuration, RTGETOPT_REQ_NOTHING }, … … 414 418 static bool g_fFSync = true; 415 419 static bool g_fMMap = true; 420 static bool g_fCopy = true; 416 421 /** @} */ 417 422 … … 451 456 /** The test directory (absolute). This will always have a trailing slash. */ 452 457 static char g_szDir[RTPATH_MAX]; 458 /** The test directory (absolute), 2nd copy for use with InDir2(). */ 459 static char g_szDir2[RTPATH_MAX]; 453 460 /** The empty test directory (absolute). This will always have a trailing slash. */ 454 461 static char g_szEmptyDir[RTPATH_MAX]; … … 508 515 g_szDir[g_cchDir + cchAppend] = '\0'; 509 516 return &g_szDir[0]; 517 } 518 519 520 /** 521 * Construct a path relative to the base test directory, 2nd copy. 522 * 523 * @returns g_szDir2. 524 * @param pszAppend What to append. 525 * @param cchAppend How much to append. 526 */ 527 DECLINLINE(char *) InDir2(const char *pszAppend, size_t cchAppend) 528 { 529 Assert(g_szDir[g_cchDir - 1] == RTPATH_SLASH); 530 memcpy(g_szDir2, g_szDir, g_cchDir); 531 memcpy(&g_szDir2[g_cchDir], pszAppend, cchAppend); 532 g_szDir2[g_cchDir + cchAppend] = '\0'; 533 return &g_szDir2[0]; 510 534 } 511 535 … … 3070 3094 if (cbFile + _16M < (uint64_t)cbFree) 3071 3095 cbFile = RT_ALIGN_64(cbFile, _64K); 3096 else if (cbFree < _32M) 3097 { 3098 RTTestSkipped(g_hTest, "Insufficent free space: %'RU64 bytes, requires >= 32MB", cbFree); 3099 return; 3100 } 3072 3101 else 3073 3102 { 3074 if (cbFree < _32M)3075 {3076 RTTestSkipped(g_hTest, "Insufficent free space: %'RU64 bytes, requires >= 32MB", cbFree);3077 return;3078 }3079 3103 cbFile = cbFree - (cbFree > _128M ? _64M : _16M); 3080 3104 cbFile = RT_ALIGN_64(cbFile, _64K); … … 3148 3172 RTTESTI_CHECK_RC(RTFileClose(hFileNoCache), VINF_SUCCESS); 3149 3173 RTTESTI_CHECK_RC(RTFileClose(hFileWriteThru), VINF_SUCCESS); 3174 RTTESTI_CHECK_RC(RTFileDelete(g_szDir), VINF_SUCCESS); 3175 } 3176 3177 3178 DECL_FORCE_INLINE(int) fsPerfCopyWorker1(const char *pszSrc, const char *pszDst) 3179 { 3180 RTFileDelete(pszDst); 3181 return RTFileCopy(pszSrc, pszDst); 3182 } 3183 3184 3185 static void fsPerfCopy(void) 3186 { 3187 RTTestISub("copy"); 3188 3189 /* 3190 * Non-existing files. 3191 */ 3192 RTTESTI_CHECK_RC(RTFileCopy(InEmptyDir(RT_STR_TUPLE("no-such-file")), 3193 InDir2(RT_STR_TUPLE("whatever"))), VERR_FILE_NOT_FOUND); 3194 RTTESTI_CHECK_RC(RTFileCopy(InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file")), 3195 InDir2(RT_STR_TUPLE("no-such-file"))), FSPERF_VERR_PATH_NOT_FOUND); 3196 RTTESTI_CHECK_RC(RTFileCopy(InDir(RT_STR_TUPLE("known-file" RTPATH_SLASH_STR "no-such-file")), 3197 InDir2(RT_STR_TUPLE("whatever"))), VERR_PATH_NOT_FOUND); 3198 3199 RTTESTI_CHECK_RC(RTFileCopy(InDir(RT_STR_TUPLE("known-file")), 3200 InEmptyDir(RT_STR_TUPLE("no-such-dir" RTPATH_SLASH_STR "no-such-file"))), FSPERF_VERR_PATH_NOT_FOUND); 3201 RTTESTI_CHECK_RC(RTFileCopy(InDir(RT_STR_TUPLE("known-file")), 3202 InDir2(RT_STR_TUPLE("known-file" RTPATH_SLASH_STR "no-such-file"))), VERR_PATH_NOT_FOUND); 3203 3204 /* 3205 * Determin the size of the test file. 3206 * We want to be able to make 1 copy of it. 3207 */ 3208 g_szDir[g_cchDir] = '\0'; 3209 RTFOFF cbFree = 0; 3210 RTTESTI_CHECK_RC_RETV(RTFsQuerySizes(g_szDir, NULL, &cbFree, NULL, NULL), VINF_SUCCESS); 3211 uint64_t cbFile = g_cbIoFile; 3212 if (cbFile + _16M < (uint64_t)cbFree) 3213 cbFile = RT_ALIGN_64(cbFile, _64K); 3214 else if (cbFree < _32M) 3215 { 3216 RTTestSkipped(g_hTest, "Insufficent free space: %'RU64 bytes, requires >= 32MB", cbFree); 3217 return; 3218 } 3219 else 3220 { 3221 cbFile = cbFree - (cbFree > _128M ? _64M : _16M); 3222 cbFile = RT_ALIGN_64(cbFile, _64K); 3223 RTTestIPrintf(RTTESTLVL_ALWAYS, "Adjusted file size to %'RU64 bytes, due to %'RU64 bytes free.\n", cbFile, cbFree); 3224 } 3225 if (cbFile < _512K * 2) 3226 { 3227 RTTestSkipped(g_hTest, "Specified test file size too small: %'RU64 bytes, requires >= 1MB", cbFile); 3228 return; 3229 } 3230 cbFile /= 2; 3231 3232 /* 3233 * Create a cbFile sized test file. 3234 */ 3235 RTFILE hFile1; 3236 RTTESTI_CHECK_RC_RETV(RTFileOpen(&hFile1, InDir(RT_STR_TUPLE("file22")), 3237 RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE | RTFILE_O_READWRITE), VINF_SUCCESS); 3238 uint8_t *pbFree = NULL; 3239 int rc = fsPerfIoPrepFile(hFile1, cbFile, &pbFree); 3240 RTMemFree(pbFree); 3241 RTTESTI_CHECK_RC(RTFileClose(hFile1), VINF_SUCCESS); 3242 if (RT_SUCCESS(rc)) 3243 { 3244 /* 3245 * Make copies. 3246 */ 3247 /* plain */ 3248 RTFileDelete(InDir2(RT_STR_TUPLE("file23"))); 3249 RTTESTI_CHECK_RC(RTFileCopy(g_szDir, g_szDir2), VINF_SUCCESS); 3250 RTTESTI_CHECK_RC(RTFileCopy(g_szDir, g_szDir2), VERR_ALREADY_EXISTS); 3251 RTTESTI_CHECK_RC(RTFileCompare(g_szDir, g_szDir2), VINF_SUCCESS); 3252 3253 /* by handle */ 3254 hFile1 = NIL_RTFILE; 3255 RTTESTI_CHECK_RC(RTFileOpen(&hFile1, g_szDir, RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READ), VINF_SUCCESS); 3256 RTFILE hFile2 = NIL_RTFILE; 3257 RTTESTI_CHECK_RC(RTFileOpen(&hFile2, g_szDir2, RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE | RTFILE_O_WRITE), VINF_SUCCESS); 3258 RTTESTI_CHECK_RC(RTFileCopyByHandles(hFile1, hFile2), VINF_SUCCESS); 3259 RTTESTI_CHECK_RC(RTFileClose(hFile2), VINF_SUCCESS); 3260 RTTESTI_CHECK_RC(RTFileClose(hFile1), VINF_SUCCESS); 3261 RTTESTI_CHECK_RC(RTFileCompare(g_szDir, g_szDir2), VINF_SUCCESS); 3262 3263 /* copy part */ 3264 hFile1 = NIL_RTFILE; 3265 RTTESTI_CHECK_RC(RTFileOpen(&hFile1, g_szDir, RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READ), VINF_SUCCESS); 3266 hFile2 = NIL_RTFILE; 3267 RTTESTI_CHECK_RC(RTFileOpen(&hFile2, g_szDir2, RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE | RTFILE_O_WRITE), VINF_SUCCESS); 3268 RTTESTI_CHECK_RC(RTFileCopyPart(hFile1, 0, hFile2, 0, cbFile / 2, 0, NULL), VINF_SUCCESS); 3269 RTTESTI_CHECK_RC(RTFileCopyPart(hFile1, cbFile / 2, hFile2, cbFile / 2, cbFile - cbFile / 2, 0, NULL), VINF_SUCCESS); 3270 RTTESTI_CHECK_RC(RTFileClose(hFile2), VINF_SUCCESS); 3271 RTTESTI_CHECK_RC(RTFileClose(hFile1), VINF_SUCCESS); 3272 RTTESTI_CHECK_RC(RTFileCompare(g_szDir, g_szDir2), VINF_SUCCESS); 3273 3274 /* 3275 * Do some benchmarking. 3276 */ 3277 #define PROFILE_COPY_FN(a_szOperation, a_fnCall) \ 3278 do \ 3279 { \ 3280 /* Estimate how many iterations we need to fill up the given timeslot: */ \ 3281 fsPerfYield(); \ 3282 uint64_t nsStart = RTTimeNanoTS(); \ 3283 uint64_t ns; \ 3284 do \ 3285 ns = RTTimeNanoTS(); \ 3286 while (ns == nsStart); \ 3287 nsStart = ns; \ 3288 \ 3289 uint64_t iIteration = 0; \ 3290 do \ 3291 { \ 3292 RTTESTI_CHECK_RC(a_fnCall, VINF_SUCCESS); \ 3293 iIteration++; \ 3294 ns = RTTimeNanoTS() - nsStart; \ 3295 } while (ns < RT_NS_10MS); \ 3296 ns /= iIteration; \ 3297 if (ns > g_nsPerNanoTSCall + 32) \ 3298 ns -= g_nsPerNanoTSCall; \ 3299 uint64_t cIterations = g_nsTestRun / ns; \ 3300 if (cIterations < 2) \ 3301 cIterations = 2; \ 3302 else if (cIterations & 1) \ 3303 cIterations++; \ 3304 \ 3305 /* Do the actual profiling: */ \ 3306 iIteration = 0; \ 3307 fsPerfYield(); \ 3308 nsStart = RTTimeNanoTS(); \ 3309 for (uint32_t iAdjust = 0; iAdjust < 4; iAdjust++) \ 3310 { \ 3311 for (; iIteration < cIterations; iIteration++)\ 3312 RTTESTI_CHECK_RC(a_fnCall, VINF_SUCCESS); \ 3313 ns = RTTimeNanoTS() - nsStart;\ 3314 if (ns >= g_nsTestRun - (g_nsTestRun / 10)) \ 3315 break; \ 3316 cIterations += cIterations / 4; \ 3317 if (cIterations & 1) \ 3318 cIterations++; \ 3319 nsStart += g_nsPerNanoTSCall; \ 3320 } \ 3321 RTTestIValueF(ns / iIteration, \ 3322 RTTESTUNIT_NS_PER_OCCURRENCE, a_szOperation " latency"); \ 3323 RTTestIValueF((uint64_t)((uint64_t)iIteration * cbFile / ((double)ns / RT_NS_1SEC)), \ 3324 RTTESTUNIT_BYTES_PER_SEC, a_szOperation " throughput"); \ 3325 RTTestIValueF((uint64_t)iIteration * cbFile, \ 3326 RTTESTUNIT_BYTES, a_szOperation " bytes"); \ 3327 RTTestIValueF(iIteration, \ 3328 RTTESTUNIT_OCCURRENCES, a_szOperation " iterations"); \ 3329 if (g_fShowDuration) \ 3330 RTTestIValueF(ns, RTTESTUNIT_NS, a_szOperation " duration"); \ 3331 } while (0) 3332 3333 PROFILE_COPY_FN("RTFileCopy/Replace", fsPerfCopyWorker1(g_szDir, g_szDir2)); 3334 3335 hFile1 = NIL_RTFILE; 3336 RTTESTI_CHECK_RC(RTFileOpen(&hFile1, g_szDir, RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READ), VINF_SUCCESS); 3337 RTFileDelete(g_szDir2); 3338 hFile2 = NIL_RTFILE; 3339 RTTESTI_CHECK_RC(RTFileOpen(&hFile2, g_szDir2, RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE | RTFILE_O_WRITE), VINF_SUCCESS); 3340 PROFILE_COPY_FN("RTFileCopyByHandles/Overwrite", RTFileCopyByHandles(hFile1, hFile2)); 3341 RTTESTI_CHECK_RC(RTFileClose(hFile2), VINF_SUCCESS); 3342 RTTESTI_CHECK_RC(RTFileClose(hFile1), VINF_SUCCESS); 3343 3344 /* We could benchmark RTFileCopyPart with various block sizes and whatnot... 3345 But it's currently well covered by the two previous operations. */ 3346 } 3347 3348 /* 3349 * Clean up. 3350 */ 3351 RTFileDelete(InDir2(RT_STR_TUPLE("file22c1"))); 3352 RTFileDelete(InDir2(RT_STR_TUPLE("file22c2"))); 3353 RTFileDelete(InDir2(RT_STR_TUPLE("file22c3"))); 3150 3354 RTTESTI_CHECK_RC(RTFileDelete(g_szDir), VINF_SUCCESS); 3151 3355 } … … 3311 3515 g_fFSync = true; 3312 3516 g_fMMap = true; 3517 g_fCopy = true; 3313 3518 break; 3314 3519 … … 3336 3541 g_fFSync = false; 3337 3542 g_fMMap = false; 3543 g_fCopy = false; 3338 3544 break; 3339 3545 … … 3363 3569 CASE_OPT(MMap); 3364 3570 CASE_OPT(IgnoreNoCache); 3571 CASE_OPT(Copy); 3365 3572 3366 3573 CASE_OPT(ShowDuration); … … 3516 3723 if (g_fReadPerf || g_fReadTests || g_fWritePerf || g_fWriteTests || g_fSeek || g_fFSync || g_fMMap) 3517 3724 fsPerfIo(); 3725 if (g_fCopy) 3726 fsPerfCopy(); 3518 3727 } 3519 3728
Note:
See TracChangeset
for help on using the changeset viewer.