diff options
author | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2014-08-12 11:16:25 -0400 |
---|---|---|
committer | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2014-08-29 13:49:08 -0400 |
commit | b983d2b0858507009c1ef1589853cf9aec8dba33 (patch) | |
tree | 3cc407c33a861171cf1141062c4a0c6b42898958 /src/mongo | |
parent | eca928dd6fdbca3b5a4e773af8f48333fee39409 (diff) | |
download | mongo-b983d2b0858507009c1ef1589853cf9aec8dba33.tar.gz |
SERVER-14129: Use fsync instead of msync for Solaris
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/util/mmap_posix.cpp | 14 | ||||
-rw-r--r-- | src/mongo/util/processinfo.h | 15 | ||||
-rw-r--r-- | src/mongo/util/processinfo_sunos5.cpp | 31 |
3 files changed, 56 insertions, 4 deletions
diff --git a/src/mongo/util/mmap_posix.cpp b/src/mongo/util/mmap_posix.cpp index 52c64249f50..20b221a885c 100644 --- a/src/mongo/util/mmap_posix.cpp +++ b/src/mongo/util/mmap_posix.cpp @@ -252,9 +252,14 @@ namespace mongo { void MemoryMappedFile::flush(bool sync) { if ( views.empty() || fd == 0 ) return; - if ( msync(viewForFlushing(), len, sync ? MS_SYNC : MS_ASYNC) ) { + + bool useFsync = sync && !ProcessInfo::preferMsyncOverFSync(); + + if ( useFsync ? + fsync(fd) != 0 : + msync(viewForFlushing(), len, sync ? MS_SYNC : MS_ASYNC) ) { // msync failed, this is very bad - log() << "msync failed: " << errnoWithDescription() + log() << (useFsync ? "fsync failed: " : "msync failed: ") << errnoWithDescription() << " file: " << filename() << endl; dataSyncFailedHandler(); } @@ -270,8 +275,11 @@ namespace mongo { if ( _view == NULL || _fd == 0 ) return; - if ( msync(_view, _len, MS_SYNC ) == 0 ) + if ( ProcessInfo::preferMsyncOverFSync() ? + msync(_view, _len, MS_SYNC ) == 0 : + fsync(_fd) == 0 ) { return; + } if ( errno == EBADF ) { // ok, we were unlocked, so this file was closed diff --git a/src/mongo/util/processinfo.h b/src/mongo/util/processinfo.h index d41b085a6eb..d415bf2eea7 100644 --- a/src/mongo/util/processinfo.h +++ b/src/mongo/util/processinfo.h @@ -103,6 +103,11 @@ namespace mongo { static bool isDataFileZeroingNeeded() { return systemInfo->fileZeroNeeded; } /** + * Determine if we need to workaround slow msync performance on Illumos/Solaris + */ + static bool preferMsyncOverFSync() { return systemInfo->preferMsyncOverFSync; } + + /** * Get extra system stats */ void appendSystemDetails( BSONObjBuilder& details ) const { @@ -162,13 +167,21 @@ namespace mongo { // bool fileZeroNeeded; + // On non-Solaris (ie, Linux, Darwin, *BSD) kernels, prefer msync. + // Illumos kernels do O(N) scans in memory of the page table during msync which + // causes high CPU, Oracle Solaris 11.2 and later modified ZFS to workaround mongodb + // Oracle Solaris Bug: + // 18658199 Speed up msync() on ZFS by 90000x with this one weird trick + bool preferMsyncOverFSync; + SystemInfo() : addrSize( 0 ), memSize( 0 ), numCores( 0 ), pageSize( 0 ), hasNuma( false ), - fileZeroNeeded (false) { + fileZeroNeeded (false), + preferMsyncOverFSync (true) { // populate SystemInfo during construction collectSystemInfo(); } diff --git a/src/mongo/util/processinfo_sunos5.cpp b/src/mongo/util/processinfo_sunos5.cpp index 37629051b20..4b989dbea91 100644 --- a/src/mongo/util/processinfo_sunos5.cpp +++ b/src/mongo/util/processinfo_sunos5.cpp @@ -44,6 +44,7 @@ #include "mongo/util/mongoutils/str.h" #include "mongo/util/processinfo.h" #include "mongo/util/scopeguard.h" +#include "mongo/util/stringutils.h" namespace mongo { @@ -145,6 +146,36 @@ namespace mongo { cpuArch = unameData.machine; hasNuma = checkNumaEnabled(); + // We prefer FSync over msync, when: + // 1. Pre-Oracle Solaris 11.2 releases + // 2. Illumos kernel releases (which is all non Oracle Solaris releases) + preferMsyncOverFSync = false; + + if (mongoutils::str::startsWith(osName, "Oracle Solaris")) { + + std::vector<std::string> versionComponents; + splitStringDelim(osVersion, &versionComponents, '.'); + + if (versionComponents.size() > 1) { + unsigned majorInt, minorInt; + Status majorStatus = + parseNumberFromString<unsigned>(versionComponents[0], &majorInt); + + Status minorStatus = + parseNumberFromString<unsigned>(versionComponents[1], &minorInt); + + if (!majorStatus.Ok() || !minorStatus.Ok()) { + warning() << "Could not parse OS version numbers from uname: " << osVersion; + } + else if ((majorInt == 11 && minorInt >= 2) || major > 11) { + preferMsyncOverFSync = true; + } + } + else { + warning() << "Could not parse OS version string from uname: " << osVersion; + } + } + BSONObjBuilder bExtra; bExtra.append("kernelVersion", unameData.release); bExtra.append("pageSize", static_cast<long long>(pageSize)); |