diff options
Diffstat (limited to 'src/mongo/client/examples/mongoperf.cpp')
-rw-r--r-- | src/mongo/client/examples/mongoperf.cpp | 336 |
1 files changed, 0 insertions, 336 deletions
diff --git a/src/mongo/client/examples/mongoperf.cpp b/src/mongo/client/examples/mongoperf.cpp deleted file mode 100644 index e5f5b2686ec..00000000000 --- a/src/mongo/client/examples/mongoperf.cpp +++ /dev/null @@ -1,336 +0,0 @@ -/* Copyright 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/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects - * for all of the code used other than as permitted herein. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you do not - * wish to do so, delete this exception statement from your version. If you - * delete this exception statement from all source files in the program, - * then also delete it in the license file. - */ - -/* - How to build and run: - - scons mongoperf - ./mongoperf -h -*/ - - -// note: mongoperf is an internal mongodb utility -// so we define the following macro -#define MONGO_EXPOSE_MACROS 1 - -#include "mongo/platform/basic.h" - -#include <iostream> - -#include <boost/filesystem/operations.hpp> - -#include "mongo/db/jsobj.h" -#include "mongo/db/json.h" -#include "mongo/db/storage/mmap_v1/logfile.h" -#include "mongo/db/storage/mmap_v1/mmap.h" -#include "mongo/platform/atomic_word.h" -#include "mongo/stdx/thread.h" -#include "mongo/util/allocator.h" -#include "mongo/util/mongoutils/str.h" -#include "mongo/util/scopeguard.h" -#include "mongo/util/time_support.h" -#include "mongo/util/timer.h" - -using namespace std; -using namespace mongo; -using namespace mongoutils::str; - -int dummy; -unsigned recSizeKB; -LogFile* lf = 0; -MemoryMappedFile* mmfFile; -char* mmf = 0; -bo options; -unsigned long long len; // file len -const unsigned PG = 4096; -unsigned nThreadsRunning = 0; - -// as this is incremented A LOT, at some point this becomes a bottleneck if very high ops/second (in -// cache) things are happening. -AtomicUInt32 iops; - -SimpleMutex m; - -int syncDelaySecs = 0; - -void syncThread() { - while (1) { - mongo::Timer t; - mmfFile->flush(true); - cout << " mmf sync took " << t.millis() - << "ms" << endl; - sleepsecs(syncDelaySecs); - } -} - -void stripTrailing(std::string& s, const char* chars) { - std::string::iterator to = s.begin(); - for (std::string::iterator i = s.begin(); i != s.end(); i++) { - // During each iteration if i finds a non-"chars" character it writes it to the - // position of t. So the part of the string left from the "to" iterator is already - // "cleared" string. - if (!contains(chars, *i)) { - if (i != to) - s.replace(to, to + 1, 1, *i); - to++; - } - } - s.erase(to, s.end()); -} - -char* round(char* x) { - size_t f = (size_t)x; - char* p = (char*)((f + PG - 1) / PG * PG); - return p; -} - -struct Aligned { - char x[8192]; - char* addr() { - return round(x); - } -}; - -unsigned long long rrand() { - // RAND_MAX is very small on windows - return (static_cast<unsigned long long>(rand()) << 15) ^ rand(); -} - -void workerThread() { - bool r = options["r"].trueValue(); - bool w = options["w"].trueValue(); - cout << "read:" << r << " write:" << w << endl; - long long su = options["sleepMicros"].numberLong(); - Aligned a; - while (1) { - unsigned long long rofs = (rrand() * PG) % len; - unsigned long long wofs = (rrand() * PG) % len; - const unsigned P = PG / 1024; - if (mmf) { - if (r) { - for (unsigned p = P; p <= recSizeKB; p += P) { - if (rofs < len) - dummy += mmf[rofs]; - rofs += PG; - } - iops.fetchAndAdd(1); - } - if (w) { - for (unsigned p = P; p <= recSizeKB; p += P) { - if (wofs < len) - mmf[wofs] = 3; - wofs += PG; - } - iops.fetchAndAdd(1); - } - } else { - if (r) { - lf->readAt(rofs, a.addr(), recSizeKB * 1024); - iops.fetchAndAdd(1); - } - if (w) { - lf->writeAt(wofs, a.addr(), recSizeKB * 1024); - iops.fetchAndAdd(1); - } - } - long long micros = su / nThreadsRunning; - if (micros) { - sleepmicros(micros); - } - } -} - -void go() { - verify(options["r"].trueValue() || options["w"].trueValue()); - - recSizeKB = options["recSizeKB"].numberInt(); - if (recSizeKB == 0) - recSizeKB = 4; - verify(recSizeKB <= 64000 && recSizeKB > 0); - - auto opCtx = cc().makeOperationContext(); - MemoryMappedFile f(opCtx.get()); - ON_BLOCK_EXIT([&f, &opCtx] { - LockMongoFilesExclusive lock(opCtx.get()); - f.close(opCtx.get()); - }); - - cout << "creating test file size:"; - len = options["fileSizeMB"].numberLong(); - if (len == 0) - len = 1; - cout << len << "MB ..." << endl; - - if (0 && len > 2000 && !options["mmf"].trueValue()) { - // todo make tests use 64 bit offsets in their i/o -- i.e. adjust LogFile::writeAt and such - cout << "\nsizes > 2GB not yet supported with mmf:false" << endl; - return; - } - len *= 1024 * 1024; - const char* fname = "./mongoperf__testfile__tmp"; - try { - boost::filesystem::remove(fname); - } catch (...) { - cout << "error deleting file " << fname << endl; - return; - } - lf = new LogFile(fname, true); - // needs to be big as we are using synchronousAppend. if we used a regular MongoFile it - // wouldn't have to be - const unsigned sz = 1024 * 1024 * 32; - char* buf = (char*)mongoMalloc(sz + 4096); - const char* p = round(buf); - for (unsigned long long i = 0; i < len; i += sz) { - lf->synchronousAppend(p, sz); - if (i % (1024ULL * 1024 * 1024) == 0 && i) { - cout << i / (1024ULL * 1024 * 1024) << "GB..." << endl; - } - } - BSONObj& o = options; - - if (o["mmf"].trueValue()) { - delete lf; - lf = 0; - mmfFile = new MemoryMappedFile(opCtx.get()); - mmf = (char*)mmfFile->map(opCtx.get(), fname); - verify(mmf); - - syncDelaySecs = options["syncDelay"].numberInt(); - if (syncDelaySecs) { - stdx::thread t(syncThread); - t.detach(); - } - } - - cout << "testing..." << endl; - - cout << "options:" << o.toString() << endl; - unsigned wthr = 1; - if (!o["nThreads"].eoo()) { - wthr = (unsigned)o["nThreads"].Int(); - } - cout << "wthr " << wthr << endl; - - if (wthr < 1) { - cout << "bad threads field value" << endl; - return; - } - unsigned i = 0; - unsigned d = 1; - unsigned& nthr = nThreadsRunning; - while (1) { - if (i++ % 8 == 0) { - if (nthr < wthr) { - while (nthr < wthr && nthr < d) { - nthr++; - stdx::thread w(workerThread); - w.detach(); - } - cout << "new thread, total running : " << nthr << endl; - d *= 2; - } - } - sleepsecs(1); - unsigned long long w = iops.loadRelaxed(); - iops.store(0); - w /= 1; // 1 secs - cout << w << " ops/sec "; - if (mmf == 0) - // only writing 4 bytes with mmf so we don't say this - cout << (w * PG / 1024 / 1024) << " MB/sec"; - cout << endl; - } -} - -int main(int argc, char* argv[]) { - try { - cout << "mongoperf" << endl; - - if (argc > 1) { - cout << - - "\n" - "usage:\n" - "\n" - " mongoperf < myjsonconfigfile\n" - "\n" - " {\n" - " nThreads:<n>, // number of threads (default 1)\n" - " fileSizeMB:<n>, // test file size (default 1MB)\n" - " sleepMicros:<n>, // pause for sleepMicros/nThreads between each operation " - "(default 0)\n" - " mmf:<bool>, // if true do i/o's via memory mapped files (default " - "false)\n" - " r:<bool>, // do reads (default false)\n" - " w:<bool>, // do writes (default false)\n" - " recSizeKB:<n>, // size of each write (default 4KB)\n" - " syncDelay:<n> // secs between fsyncs, like --syncdelay in mongod. " - "(default 0/never)\n" - " }\n" - "\n" - "mongoperf is a performance testing tool. the initial tests are of disk subsystem " - "performance; \n" - " tests of mongos and mongod will be added later.\n" - "most fields are optional.\n" - "non-mmf io is direct io (no caching). use a large file size to test making the " - "heads\n" - " move significantly and to avoid i/o coalescing\n" - "mmf io uses caching (the file system cache).\n" - "\n" - - << endl; - return EXIT_SUCCESS; - } - - cout << "use -h for help" << endl; - - char input[1024]; - memset(input, 0, sizeof(input)); - cin.read(input, 1000); - if (*input == 0) { - cout << "error no options found on stdin for mongoperf" << endl; - return EXIT_FAILURE; - } - - string s = input; - stripTrailing(s, " \n\r\0x1a"); - try { - options = fromjson(s); - } catch (...) { - cout << "couldn't parse json options. input was:\n|" << s << "|" << endl; - return EXIT_FAILURE; - } - cout << "parsed options:\n" << options.toString() << endl; - - go(); - } catch (DBException& e) { - cout << "caught DBException " << e.toString() << endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} |