summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2014-08-12 11:16:25 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2014-08-29 13:49:08 -0400
commitb983d2b0858507009c1ef1589853cf9aec8dba33 (patch)
tree3cc407c33a861171cf1141062c4a0c6b42898958 /src/mongo
parenteca928dd6fdbca3b5a4e773af8f48333fee39409 (diff)
downloadmongo-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.cpp14
-rw-r--r--src/mongo/util/processinfo.h15
-rw-r--r--src/mongo/util/processinfo_sunos5.cpp31
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));