Fennel: /home/pub/open/dev/fennel/test/PagingTestBase.cpp Source File (original) (raw)

00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 00024 #include "fennel/common/CommonPreamble.h" 00025 #include "fennel/test/PagingTestBase.h" 00026 #include "fennel/common/FileSystem.h" 00027 #include "fennel/device/RandomAccessFileDevice.h" 00028 #include "fennel/synch/Thread.h" 00029 #include "fennel/cache/CachePage.h" 00030 #include "fennel/cache/CacheImpl.h" 00031 #include "fennel/cache/RandomVictimPolicy.h" 00032 #include <boost/test/test_tools.hpp> 00033 00034 00035 #include 00036 00037 using namespace fennel; 00038 00039 static boost::thread_specific_ptrstd::subtractive_rng g_pRNG; 00040 00041 void PagingTestBase::threadInit() 00042 { 00043 ThreadedTestBase::threadInit(); 00044 g_pRNG.reset(new std::subtractive_rng()); 00045 } 00046 00047 void PagingTestBase::threadTerminate() 00048 { 00049 g_pRNG.reset(); 00050 ThreadedTestBase::threadTerminate(); 00051 } 00052 00053 uint PagingTestBase::generateRandomNumber(uint iMax) 00054 { 00055 return (*g_pRNG)(iMax); 00056 } 00057 00058 void PagingTestBase::fillPage(CachePage &page,uint x) 00059 { 00060 uint *p = reinterpret_cast<uint *>(page.getWritableData()); 00061 assert(cbPageUsable); 00062 uint n = cbPageUsable / sizeof(uint); 00063 for (uint i = 0; i < n; i++) { 00064 p[i] = x + i; 00065 } 00066 uint r = generateRandomNumber(n); 00067 p[r] = 0; 00068 } 00069 00070 void PagingTestBase::verifyPage(CachePage &page,uint x) 00071 { 00072 uint const *p = reinterpret_cast<uint const *>(page.getReadableData()); 00073 assert(cbPageUsable); 00074 uint n = cbPageUsable / sizeof(uint); 00075 uint nZeros = 0; 00076 for (uint i = 0; i < n; i++) { 00077 if (p[i] != x + i) { 00078 assert(!p[i]); 00079 nZeros++; 00080 } 00081 } 00082 assert(nZeros < 2); 00083 } 00084 00085 bool PagingTestBase::testOp(OpType opType,uint iPage,bool bNice) 00086 { 00087 CachePage *pPage = lockPage(opType,iPage); 00088 LockMode lockMode = getLockMode(opType); 00089 if (!pPage) { 00090
00091 assert(lockMode >= LOCKMODE_S_NOWAIT); 00092 return false; 00093 } 00094 CachePage &page = *pPage; 00095 if (lockMode == LOCKMODE_S 00096 || lockMode == LOCKMODE_S_NOWAIT) 00097 { 00098 verifyPage(page,iPage); 00099 } else { 00100 fillPage(page,iPage); 00101 } 00102 switch (lockMode) { 00103 case LOCKMODE_X_NOWAIT: 00104 lockMode = LOCKMODE_X; 00105 break; 00106 case LOCKMODE_S_NOWAIT: 00107 lockMode = LOCKMODE_S; 00108 break; 00109 default: 00110 break; 00111 } 00112 if (bNice) { 00113 getCache().nicePage(page); 00114 } 00115 unlockPage(page,lockMode); 00116 return true; 00117 } 00118 00119 char const *PagingTestBase::getOpName(OpType opType) 00120 { 00121 switch (opType) { 00122 case OP_ALLOCATE: 00123 return "allocate"; 00124 case OP_READ_SEQ: 00125 return "sequential read"; 00126 case OP_WRITE_SEQ: 00127 return "sequential write"; 00128 case OP_READ_RAND: 00129 return "random read"; 00130 case OP_WRITE_RAND: 00131 return "random write"; 00132 case OP_READ_NOWAIT: 00133 return "read no-wait"; 00134 case OP_WRITE_NOWAIT: 00135 return "write no-wait"; 00136 case OP_WRITE_SKIP: 00137 return "write every n pages"; 00138 default: 00139 permAssert(false); 00140 } 00141 } 00142 00143 LockMode PagingTestBase::getLockMode(OpType opType) 00144 { 00145 switch (opType) { 00146 case OP_ALLOCATE: 00147 return LOCKMODE_X; 00148 case OP_READ_SEQ: 00149 return LOCKMODE_S; 00150 case OP_WRITE_SEQ: 00151 return LOCKMODE_X; 00152 case OP_READ_RAND: 00153 return LOCKMODE_S; 00154 case OP_WRITE_RAND: 00155 return LOCKMODE_X; 00156 case OP_READ_NOWAIT: 00157 return LOCKMODE_S_NOWAIT; 00158 case OP_WRITE_NOWAIT: 00159 return LOCKMODE_X_NOWAIT; 00160 case OP_WRITE_SKIP: 00161 return LOCKMODE_X; 00162 default: 00163 permAssert(false); 00164 } 00165 } 00166 00167 void PagingTestBase::testSequentialOp(OpType opType) 00168 { 00169 uint n = 0; 00170 for (uint i = 0; i < nDiskPages; i++) { 00171 if (testOp(opType,i,true)) { 00172 n++; 00173 } 00174 } 00175 StrictMutexGuard mutexGuard(logMutex); 00176 BOOST_MESSAGE( 00177 "completed " << n << " " << getOpName(opType) << " ops"); 00178 } 00179 00180 void PagingTestBase::testRandomOp(OpType opType) 00181 { 00182 uint n = 0; 00183 for (uint i = 0; i < nRandomOps; i++) { 00184 uint iPage = generateRandomNumber(nDiskPages); 00185 bool bNice = (generateRandomNumber(nRandomOps) == 0); 00186 if (testOp(opType,iPage,bNice)) { 00187 n++; 00188 } 00189 } 00190 StrictMutexGuard mutexGuard(logMutex); 00191 BOOST_MESSAGE( 00192 "completed " << n << " " << getOpName(opType) << " ops"); 00193 00194 } 00195 00196 void PagingTestBase::testSkipOp(OpType opType, uint n) 00197 { 00198 uint numOps = 0; 00199 for (uint i = 0; i < nDiskPages; i += n) { 00200 if (testOp(opType,i,true)) { 00201 numOps++; 00202 } 00203 } 00204 StrictMutexGuard mutexGuard(logMutex); 00205 BOOST_MESSAGE( 00206 "completed " << numOps << " " << getOpName(opType) << " ops"); 00207 } 00208 00209 void PagingTestBase::testScratch() 00210 { 00211 for (uint i = 0; i < nRandomOps; i++) { 00212 CachePage &page = getCache().lockScratchPage(); 00213 fillPage(page,generateRandomNumber(10000)); 00214 getCache().unlockPage(page,LOCKMODE_X); 00215 } 00216 StrictMutexGuard mutexGuard(logMutex); 00217 BOOST_MESSAGE("completed " << nRandomOps << " random scratch ops"); 00218 } 00219 00220 void PagingTestBase::testPrefetch() 00221 { 00222
00223 uint n = 3; 00224 for (uint i = 0; i < n; i++) { 00225 uint iPage = generateRandomNumber(nDiskPages); 00226 prefetchPage(iPage); 00227 } 00228
00229 snooze(1); 00230 StrictMutexGuard mutexGuard(logMutex); 00231 BOOST_MESSAGE("completed " << n << " random prefetch ops"); 00232 } 00233 00234 void PagingTestBase::testPrefetchBatch() 00235 { 00236
00237 uint n = 2; 00238 uint nPagesPerBatch = 4; 00239 for (uint i = 0; i < n; i++) { 00240 uint iPage = generateRandomNumber(nDiskPages - nPagesPerBatch); 00241 prefetchBatch(iPage,nPagesPerBatch); 00242 } 00243
00244 snooze(1); 00245 StrictMutexGuard mutexGuard(logMutex); 00246 BOOST_MESSAGE("completed " << n << " random prefetch batch ops"); 00247 } 00248 00249 void PagingTestBase::testAllocateAll() 00250 { 00251 testSequentialOp(OP_ALLOCATE); 00252 } 00253 00254 void PagingTestBase::testSequentialRead() 00255 { 00256 testSequentialOp(OP_READ_SEQ); 00257 } 00258 00259 void PagingTestBase::testSequentialWrite() 00260 { 00261 testSequentialOp(OP_WRITE_SEQ); 00262 } 00263 00264 void PagingTestBase::testRandomRead() 00265 { 00266 testRandomOp(OP_READ_RAND); 00267 } 00268 00269 void PagingTestBase::testRandomWrite() 00270 { 00271 testRandomOp(OP_WRITE_RAND); 00272 } 00273 00274 void PagingTestBase::testSkipWrite(uint n) 00275 { 00276 testSkipOp(OP_WRITE_SKIP, n); 00277 } 00278 00279 void PagingTestBase::testAllocate() 00280 { 00281 permAssert(false); 00282 } 00283 00284 void PagingTestBase::testDeallocate() 00285 { 00286 permAssert(false); 00287 } 00288 00289 void PagingTestBase::testCheckpoint() 00290 { 00291 DeviceIdPagePredicate pagePredicate(dataDeviceId); 00292 getCache().checkpointPages(pagePredicate,CHECKPOINT_FLUSH_ALL); 00293 } 00294 00295 void PagingTestBase::testCheckpointGuarded() 00296 { 00297 snooze(nSecondsBetweenCheckpoints); 00298 StrictMutexGuard logGuard(logMutex); 00299 BOOST_MESSAGE("checkpoint started"); 00300 logGuard.unlock(); 00301 SXMutexExclusiveGuard checkpointExclusiveGuard(checkpointMutex); 00302 testCheckpoint(); 00303 checkpointExclusiveGuard.unlock(); 00304 logGuard.lock(); 00305 BOOST_MESSAGE("checkpoint completed"); 00306 } 00307 00308 void PagingTestBase::testCacheResize() 00309 { 00310 snooze(nSeconds / 3); 00311 getCache().setAllocatedPageCount(nMemPages / 2); 00312 StrictMutexGuard mutexGuard(logMutex); 00313 BOOST_MESSAGE("shrank cache"); 00314 mutexGuard.unlock(); 00315 snooze(nSeconds / 3); 00316 getCache().setAllocatedPageCount(nMemPages - 1); 00317 mutexGuard.lock(); 00318 BOOST_MESSAGE("expanded cache"); 00319 mutexGuard.unlock(); 00320 } 00321 00322 PagingTestBase::PagingTestBase() 00323 { 00324 nRandomOps = configMap.getIntParam("randomOps",5000); 00325 nSecondsBetweenCheckpoints = configMap.getIntParam("checkpointInterval",20); 00326 bTestResize = configMap.getIntParam("resizeCache",1); 00327 checkpointMutex.setSchedulingPolicy(SXMutex::SCHEDULE_FAVOR_EXCLUSIVE); 00328 00329 threadCounts.resize(OP_MAX,-1); 00330 00331 threadCounts[OP_READ_SEQ] = configMap.getIntParam( 00332 "readSeqThreads",-1); 00333 threadCounts[OP_WRITE_SEQ] = configMap.getIntParam( 00334 "writeSeqThreads",-1); 00335 threadCounts[OP_READ_RAND] = configMap.getIntParam( 00336 "readRandThreads",-1); 00337 threadCounts[OP_WRITE_RAND] = configMap.getIntParam( 00338 "writeRandThreads",-1); 00339 threadCounts[OP_READ_NOWAIT] = configMap.getIntParam( 00340 "readNoWaitThreads",-1); 00341 threadCounts[OP_WRITE_NOWAIT] = configMap.getIntParam( 00342 "writeNoWaitThreads",-1); 00343 threadCounts[OP_WRITE_SKIP] = configMap.getIntParam( 00344 "writeSkipThreads",-1); 00345 threadCounts[OP_SCRATCH] = configMap.getIntParam( 00346 "scratchThreads",-1); 00347 threadCounts[OP_PREFETCH] = configMap.getIntParam( 00348 "prefetchThreads",-1); 00349 threadCounts[OP_PREFETCH_BATCH] = configMap.getIntParam( 00350 "prefetchBatchThreads",-1); 00351 threadCounts[OP_ALLOCATE] = configMap.getIntParam( 00352 "allocateThreads",-1); 00353 threadCounts[OP_DEALLOCATE] = configMap.getIntParam( 00354 "deallocateThreads",-1); 00355 00356 if (nSecondsBetweenCheckpoints < nSeconds) { 00357 threadCounts[OP_CHECKPOINT] = 1; 00358 } else { 00359 threadCounts[OP_CHECKPOINT] = 0; 00360 } 00361 00362 if (bTestResize) { 00363 threadCounts[OP_RESIZE_CACHE] = 1; 00364 } else { 00365 threadCounts[OP_RESIZE_CACHE] = 0; 00366 } 00367 00368 cbPageUsable = 0; 00369 00370 threadInit(); 00371 } 00372 00373 PagingTestBase::~PagingTestBase() 00374 { 00375 threadTerminate(); 00376 } 00377 00378 bool PagingTestBase::testThreadedOp(int iOp) 00379 { 00380 SXMutexSharedGuard checkpointSharedGuard(checkpointMutex,false); 00381 assert(iOp < OP_MAX); 00382 OpType op = static_cast(iOp); 00383 switch (op) { 00384 case PagingTestBase::OP_WRITE_SEQ: 00385 checkpointSharedGuard.lock(); 00386
00387 case PagingTestBase::OP_READ_SEQ: 00388 testSequentialOp(op); 00389 break; 00390 case PagingTestBase::OP_WRITE_RAND: 00391 case PagingTestBase::OP_WRITE_NOWAIT: 00392 checkpointSharedGuard.lock(); 00393
00394 case PagingTestBase::OP_READ_RAND: 00395 case PagingTestBase::OP_READ_NOWAIT: 00396 testRandomOp(op); 00397 break; 00398 case PagingTestBase::OP_WRITE_SKIP: 00399 checkpointSharedGuard.lock(); 00400 testSkipOp(op, 5); 00401 break; 00402 case PagingTestBase::OP_SCRATCH: 00403 testScratch(); 00404 break; 00405 case PagingTestBase::OP_PREFETCH: 00406 testPrefetch(); 00407 break; 00408 case PagingTestBase::OP_PREFETCH_BATCH: 00409 testPrefetchBatch(); 00410 break; 00411 case PagingTestBase::OP_ALLOCATE: 00412 checkpointSharedGuard.lock(); 00413 testAllocate(); 00414 break; 00415 case PagingTestBase::OP_DEALLOCATE: 00416 checkpointSharedGuard.lock(); 00417 testDeallocate(); 00418 break; 00419 case PagingTestBase::OP_CHECKPOINT: 00420 testCheckpointGuarded(); 00421 break; 00422 case PagingTestBase::OP_RESIZE_CACHE: 00423 testCacheResize(); 00424 return false; 00425 default: 00426 permAssert(false); 00427 } 00428 return true; 00429 } 00430 00431 void PagingTestBase::testMultipleThreads() 00432 { 00433 openStorage(DeviceMode::createNew); 00434 testAllocateAll(); 00435 runThreadedTestCase(); 00436 } 00437 00438