/** We need to remap the private views periodically. otherwise they would become very large. Call within write lock. */ void REMAPPRIVATEVIEW() { static unsigned startAt; static unsigned long long lastRemap; dbMutex.assertWriteLocked(); dbMutex._remapPrivateViewRequested = false; assert( !commitJob.hasWritten() ); if( 0 ) { log() << "TEMP remapprivateview disabled for testing - will eventually run oom in this mode if db bigger than ram" << endl; return; } // we want to remap all private views about every 2 seconds. there could be ~1000 views so // we do a little each pass; beyond the remap time, more significantly, there will be copy on write // faults after remapping, so doing a little bit at a time will avoid big load spikes on // remapping. unsigned long long now = curTimeMicros64(); double fraction = (now-lastRemap)/20000000.0; set<MongoFile*>& files = MongoFile::getAllFiles(); unsigned sz = files.size(); if( sz == 0 ) return; unsigned ntodo = (unsigned) (sz * fraction); if( ntodo < 1 ) ntodo = 1; if( ntodo > sz ) ntodo = sz; const set<MongoFile*>::iterator b = files.begin(); const set<MongoFile*>::iterator e = files.end(); set<MongoFile*>::iterator i = b; // skip to our starting position for( unsigned x = 0; x < startAt; x++ ) { i++; if( i == e ) i = b; } startAt = (startAt + ntodo) % sz; // mark where to start next time for( unsigned x = 0; x < ntodo; x++ ) { dassert( i != e ); if( (*i)->isMongoMMF() ) { MongoMMF *mmf = (MongoMMF*) *i; assert(mmf); if( mmf->willNeedRemap() ) { mmf->willNeedRemap() = false; mmf->remapThePrivateView(); } i++; if( i == e ) i = b; } } }
/** We need to remap the private views periodically. otherwise they would become very large. Call within write lock. */ void _REMAPPRIVATEVIEW() { // todo: Consider using ProcessInfo herein and watching for getResidentSize to drop. that could be a way // to assure very good behavior here. static unsigned startAt; static unsigned long long lastRemap; dbMutex.assertWriteLocked(); dbMutex._remapPrivateViewRequested = false; assert( !commitJob.hasWritten() ); // we want to remap all private views about every 2 seconds. there could be ~1000 views so // we do a little each pass; beyond the remap time, more significantly, there will be copy on write // faults after remapping, so doing a little bit at a time will avoid big load spikes on // remapping. unsigned long long now = curTimeMicros64(); double fraction = (now-lastRemap)/2000000.0; if( cmdLine.durOptions & CmdLine::DurAlwaysRemap ) fraction = 1; lastRemap = now; RWLockRecursive::Shared lk(MongoFile::mmmutex); set<MongoFile*>& files = MongoFile::getAllFiles(); unsigned sz = files.size(); if( sz == 0 ) return; { // be careful not to use too much memory if the write rate is // extremely high double f = privateMapBytes / ((double)UncommittedBytesLimit); if( f > fraction ) { fraction = f; } privateMapBytes = 0; } unsigned ntodo = (unsigned) (sz * fraction); if( ntodo < 1 ) ntodo = 1; if( ntodo > sz ) ntodo = sz; const set<MongoFile*>::iterator b = files.begin(); const set<MongoFile*>::iterator e = files.end(); set<MongoFile*>::iterator i = b; // skip to our starting position for( unsigned x = 0; x < startAt; x++ ) { i++; if( i == e ) i = b; } startAt = (startAt + ntodo) % sz; // mark where to start next time for( unsigned x = 0; x < ntodo; x++ ) { dassert( i != e ); if( (*i)->isMongoMMF() ) { MongoMMF *mmf = (MongoMMF*) *i; assert(mmf); if( mmf->willNeedRemap() ) { mmf->willNeedRemap() = false; mmf->remapThePrivateView(); } i++; if( i == e ) i = b; } } }
static void _REMAPPRIVATEVIEW() { // todo: Consider using ProcessInfo herein and watching for getResidentSize to drop. that could be a way // to assure very good behavior here. static unsigned startAt; static unsigned long long lastRemap; LOG(4) << "journal REMAPPRIVATEVIEW" << endl; verify( Lock::isW() ); verify( !commitJob.hasWritten() ); // we want to remap all private views about every 2 seconds. there could be ~1000 views so // we do a little each pass; beyond the remap time, more significantly, there will be copy on write // faults after remapping, so doing a little bit at a time will avoid big load spikes on // remapping. unsigned long long now = curTimeMicros64(); double fraction = (now-lastRemap)/2000000.0; if( cmdLine.durOptions & CmdLine::DurAlwaysRemap ) fraction = 1; lastRemap = now; #if defined(_WIN32) // Note that this negatively affects performance. // We must grab the exclusive lock here because remapThePrivateView() on Windows needs // to grab it as well, due to the lack of a non-atomic way to remap a memory mapped file. // See SERVER-5723 for performance improvement. // See SERVER-5680 to see why this code is necessary. LockMongoFilesExclusive lk; #else LockMongoFilesShared lk; #endif set<MongoFile*>& files = MongoFile::getAllFiles(); unsigned sz = files.size(); if( sz == 0 ) return; { // be careful not to use too much memory if the write rate is // extremely high double f = privateMapBytes / ((double)UncommittedBytesLimit); if( f > fraction ) { fraction = f; } privateMapBytes = 0; } unsigned ntodo = (unsigned) (sz * fraction); if( ntodo < 1 ) ntodo = 1; if( ntodo > sz ) ntodo = sz; const set<MongoFile*>::iterator b = files.begin(); const set<MongoFile*>::iterator e = files.end(); set<MongoFile*>::iterator i = b; // skip to our starting position for( unsigned x = 0; x < startAt; x++ ) { i++; if( i == e ) i = b; } unsigned startedAt = startAt; startAt = (startAt + ntodo) % sz; // mark where to start next time Timer t; for( unsigned x = 0; x < ntodo; x++ ) { dassert( i != e ); if( (*i)->isMongoMMF() ) { MongoMMF *mmf = (MongoMMF*) *i; verify(mmf); if( mmf->willNeedRemap() ) { mmf->willNeedRemap() = false; mmf->remapThePrivateView(); } i++; if( i == e ) i = b; } } LOG(2) << "journal REMAPPRIVATEVIEW done startedAt: " << startedAt << " n:" << ntodo << ' ' << t.millis() << "ms" << endl; }