diff options
author | dwight <dwight@10gen.com> | 2010-11-15 22:13:48 -0500 |
---|---|---|
committer | dwight <dwight@10gen.com> | 2010-11-15 22:13:48 -0500 |
commit | 62eaedd3d21e9778c220e022f28eb67d67e81d8d (patch) | |
tree | 6c59a7e3ab63d5e3ad2d1cfd6b42f2651eb767b4 | |
parent | 16d9785166314fbfb31ea2ede0f06f2951b4b027 (diff) | |
download | mongo-62eaedd3d21e9778c220e022f28eb67d67e81d8d.tar.gz |
AlignedBuilder dur
-rw-r--r-- | db/dur.cpp | 11 | ||||
-rw-r--r-- | db/dur_journal.cpp | 9 | ||||
-rw-r--r-- | db/dur_journal.h | 4 | ||||
-rw-r--r-- | util/alignedbuilder.h | 148 |
4 files changed, 163 insertions, 9 deletions
diff --git a/db/dur.cpp b/db/dur.cpp index e80c278bdc0..5100484a858 100644 --- a/db/dur.cpp +++ b/db/dur.cpp @@ -47,6 +47,7 @@ #include "dur_journal.h" #include "../util/mongoutils/hash.h" #include "../util/timer.h" +#include "../util/alignedbuilder.h" namespace mongo { @@ -110,7 +111,7 @@ namespace mongo { } /** caller handles locking */ - static bool PREPLOGBUFFER(BufBuilder& bb) { + static bool PREPLOGBUFFER(AlignedBuilder& bb) { if( writes.empty() ) return false; @@ -169,18 +170,18 @@ namespace mongo { return true; } - static void WRITETOJOURNAL(const BufBuilder& bb) { + static void WRITETOJOURNAL(const AlignedBuilder& bb) { journal(bb); } - static void _go(BufBuilder& bb) { + static void _go(AlignedBuilder& bb) { PREPLOGBUFFER(bb); // todo: add double buffering so we can be (not even read locked) during WRITETOJOURNAL WRITETOJOURNAL(bb); } - static void go(BufBuilder& bb) { + static void go(AlignedBuilder& bb) { { readlocktry lk("", 1000); if( lk.got() ) { @@ -197,7 +198,7 @@ namespace mongo { static void durThread() { Client::initThread("dur"); const int HowOftenToGroupCommitMs = 100; - BufBuilder bb(1024 * 1024 * 16); // reuse to avoid any heap fragmentation + AlignedBuilder bb(1024 * 1024 * 16); // reuse to avoid any heap fragmentation while( 1 ) { try { int millis = HowOftenToGroupCommitMs; diff --git a/db/dur_journal.cpp b/db/dur_journal.cpp index f6ea26bb65a..a557c90e9ec 100644 --- a/db/dur_journal.cpp +++ b/db/dur_journal.cpp @@ -25,6 +25,7 @@ #include "dur_journal.h" #include "../util/logfile.h" #include "../util/timer.h" +#include "../util/alignedbuilder.h" #include <boost/static_assert.hpp> #undef assert #define assert MONGO_assert @@ -34,6 +35,8 @@ namespace mongo { using namespace mongoutils; + class AlignedBuilder; + namespace dur { BOOST_STATIC_ASSERT( sizeof(JHeader) == 8192 ); BOOST_STATIC_ASSERT( sizeof(JSectHeader) == 8 ); @@ -66,7 +69,7 @@ namespace mongo { void open(); void rotate(); - void journal(const BufBuilder& b); + void journal(const AlignedBuilder& b); path getFilePathFor(int filenumber) const; }; @@ -170,10 +173,10 @@ namespace mongo { /** write to journal */ - void journal(const BufBuilder& b) { + void journal(const AlignedBuilder& b) { j.journal(b); } - void Journal::journal(const BufBuilder& b) { + void Journal::journal(const AlignedBuilder& b) { try { /* todo: roll if too big */ if( lf == 0 ) diff --git a/db/dur_journal.h b/db/dur_journal.h index 2f1685aca0d..b0b0310014b 100644 --- a/db/dur_journal.h +++ b/db/dur_journal.h @@ -19,6 +19,8 @@ #pragma once namespace mongo { + class AlignedBuilder; + namespace dur { /** assure journal/ dir exists. throws */ @@ -31,7 +33,7 @@ namespace mongo { void journalRotate(); /** write/append to journal */ - void journal(const BufBuilder& b); + void journal(const AlignedBuilder& b); /** flag that something has gone wrong */ void journalingFailure(const char *msg); diff --git a/util/alignedbuilder.h b/util/alignedbuilder.h new file mode 100644 index 00000000000..b97c10da9ab --- /dev/null +++ b/util/alignedbuilder.h @@ -0,0 +1,148 @@ +// @file alignedbuilder.h
+
+/** +* Copyright (C) 2009 10gen Inc. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License, version 3, +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#pragma once + +namespace mongo { + + /** a page-aligned BufBuilder. */ + class AlignedBuilder { + public: + AlignedBuilder(unsigned init_size) : _size(init_size) { + _data = (char *) _malloc(_size); + if( _data == 0 ) + msgasserted(10000, "out of memory AlignedBuilder"); + _len = 0; + } + ~AlignedBuilder() { kill(); } + + /** reset for a re-use */ + void reset() { _len = 0; } + + /** leave room for some stuff later */ + char* skip(unsigned n) { return grow(n); } + + /** note this may be deallocated (realloced) if you keep writing or reset(). */ + const char* buf() const { return _data; } + + void appendChar(char j){ + *((char*)grow(sizeof(char))) = j; + } + void appendNum(char j){ + *((char*)grow(sizeof(char))) = j; + } + void appendNum(short j) { + *((short*)grow(sizeof(short))) = j; + } + void appendNum(int j) { + *((int*)grow(sizeof(int))) = j; + } + void appendNum(unsigned j) { + *((unsigned*)grow(sizeof(unsigned))) = j; + } + void appendNum(bool j) { + *((bool*)grow(sizeof(bool))) = j; + } + void appendNum(double j) { + *((double*)grow(sizeof(double))) = j; + } + void appendNum(long long j) { + *((long long*)grow(sizeof(long long))) = j; + } + void appendNum(unsigned long long j) { + *((unsigned long long*)grow(sizeof(unsigned long long))) = j; + } + + void appendBuf(const void *src, size_t len) { + memcpy(grow((unsigned) len), src, len); + } + + template<class T> + void appendStruct(const T& s) { + appendBuf(&s, sizeof(T)); + } + + void appendStr(const StringData &str , bool includeEOO = true ) { + const unsigned len = str.size() + ( includeEOO ? 1 : 0 ); + memcpy(grow(len), str.data(), len); + } + + /** @return the in-use length */ + unsigned len() const { return _len; } + + private: + /** returns the pre-grow write position */ + inline char* grow(unsigned by) { + unsigned oldlen = _len; + _len += by; + if ( _len > _size ) { + grow_reallocate(); + } + return _data + oldlen; + } + + /* "slow" portion of 'grow()' */ + void NOINLINE_DECL grow_reallocate(){ + unsigned a = _size * 2; + assert( a ); + if ( _len > a ) + a = _len + 16 * 1024; + assert( a < 0x20000000 ); + _data = (char *) _realloc(_data, a, _len); + _size = a; + } + + static const unsigned Alignment = 8192; + static void _free(void *p) { +#if defined(_WIN32) + VirtualFree(p, 0, MEM_RELEASE); +#else + free(p); +#endif + } + static void* _malloc(unsigned sz) { +#if defined(_WIN32) + void *p = VirtualAlloc(0, sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+ return p;
+#elif defined(posix_memalign) + void *p = 0; + int res = posix_memalign(&p, Alignment, sz);
+ msgasserted(10000, "out of memory AlignedBuilder", res == 0); +#else + void *p = malloc(sz); + assert( ((size_t) p) % Alignment == 0 ); + return p; +#endif + } + static void* _realloc(void *ptr, unsigned newSize, unsigned oldSize) {
+ void *p = _malloc(newSize);
+ memcpy(p, ptr, oldSize);
+ _free(ptr);
+ return p;
+ }
+ void kill() { + _free(_data); + _data = 0; + } + + char *_data; + unsigned _len; + unsigned _size; + }; + +} |