2011-10-28 12:06:29 -04:00
|
|
|
/*
|
|
|
|
|
How to build and run:
|
|
|
|
|
|
2011-11-07 10:25:06 -05:00
|
|
|
(out of date) : g++ -o mongoperf -I .. mongoperf.cpp mongo_client_lib.cpp -lboost_thread-mt -lboost_filesystem
|
2011-10-28 12:06:29 -04:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include "../dbclient.h" // the mongo c++ driver
|
2011-10-31 18:22:38 -04:00
|
|
|
#include "../../util/mmap.h"
|
|
|
|
|
#include <assert.h>
|
2011-11-06 17:42:44 -05:00
|
|
|
#include "../../util/logfile.h"
|
|
|
|
|
#include "../../util/time_support.h"
|
|
|
|
|
#include "../../bson/util/atomic_int.h"
|
2011-10-28 12:06:29 -04:00
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
using namespace mongo;
|
|
|
|
|
using namespace bson;
|
|
|
|
|
|
2011-11-06 17:42:44 -05:00
|
|
|
LogFile *lf = 0;
|
|
|
|
|
|
|
|
|
|
//MemoryMappedFile m;
|
2011-10-31 18:22:38 -04:00
|
|
|
bo options;
|
2011-11-06 17:42:44 -05:00
|
|
|
unsigned long long len; // file len
|
|
|
|
|
const unsigned PG = 4096;
|
|
|
|
|
unsigned nThreadsRunning = 0;
|
2011-11-07 10:25:06 -05:00
|
|
|
char *mmf = 0;
|
2011-11-06 17:42:44 -05:00
|
|
|
AtomicUInt writes;
|
2011-10-31 18:22:38 -04:00
|
|
|
|
2011-11-06 17:42:44 -05:00
|
|
|
void writer() {
|
|
|
|
|
long long su = options["sleepMicros"].numberLong();
|
|
|
|
|
char abuf[PG];
|
|
|
|
|
while( 1 ) {
|
|
|
|
|
int x = rand();
|
|
|
|
|
unsigned long long ofs = (x * PG) % len;
|
|
|
|
|
lf->writeAt((unsigned) ofs, abuf, PG);
|
|
|
|
|
writes++;
|
|
|
|
|
long long micros = su / nThreadsRunning;
|
|
|
|
|
if( micros ) {
|
|
|
|
|
sleepmicros(micros);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-10-28 12:06:29 -04:00
|
|
|
}
|
|
|
|
|
|
2011-10-31 18:22:38 -04:00
|
|
|
void go() {
|
2011-11-07 10:25:06 -05:00
|
|
|
MemoryMappedFile f;
|
2011-10-31 18:22:38 -04:00
|
|
|
cout << "create test file" << endl;
|
2011-11-06 17:42:44 -05:00
|
|
|
len = options["fileSizeMB"].numberLong();
|
2011-10-31 18:22:38 -04:00
|
|
|
if( len == 0 ) len = 1;
|
2011-11-06 17:42:44 -05:00
|
|
|
cout << "test fileSizeMB : " << len << endl;
|
|
|
|
|
len *= 1024 * 1024;
|
2011-11-07 10:25:06 -05:00
|
|
|
const char *fname = "mongoperf__testfile__tmp";
|
|
|
|
|
lf = new LogFile(fname);
|
2011-11-06 17:42:44 -05:00
|
|
|
const unsigned sz = 1024 * 256;
|
|
|
|
|
char buf[sz];
|
|
|
|
|
for( unsigned i = 0; i < len; i+= sz ) {
|
|
|
|
|
lf->synchronousAppend(buf, sz);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//void *p = m.create("mongoperf__testfile__tmp", len * 1024 * 1024, true);
|
|
|
|
|
//assert(p);
|
2011-10-31 18:22:38 -04:00
|
|
|
|
2011-11-07 10:25:06 -05:00
|
|
|
if( o["mmf"].trueValue() ) {
|
|
|
|
|
mmf = f.map(fname);
|
|
|
|
|
assert( mmf );
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-31 18:22:38 -04:00
|
|
|
cout << "testing..."<< endl;
|
|
|
|
|
|
|
|
|
|
BSONObj& o = options;
|
2011-11-06 17:42:44 -05:00
|
|
|
unsigned wthr = (unsigned) o["nThreads"].Int();
|
|
|
|
|
if( wthr < 1 ) {
|
|
|
|
|
cout << "bad threads field value" << endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
unsigned i = 0;
|
|
|
|
|
unsigned d = 1;
|
|
|
|
|
unsigned &nthr = nThreadsRunning;
|
|
|
|
|
while( 1 ) {
|
|
|
|
|
if( i++ % 4 == 0 ) {
|
|
|
|
|
if( nthr < wthr ) {
|
|
|
|
|
while( nthr < wthr && nthr < d ) {
|
|
|
|
|
nthr++;
|
|
|
|
|
boost::thread w(writer);
|
|
|
|
|
}
|
|
|
|
|
cout << "new thread, total running : " << nthr << endl;
|
|
|
|
|
d *= 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sleepsecs(4);
|
|
|
|
|
unsigned long long w = writes.get();
|
|
|
|
|
writes.zero();
|
|
|
|
|
w /= 4;
|
|
|
|
|
cout << w << " ops/sec " << (w * PG / 1024 / 1024) << " MB/sec" << endl;
|
2011-10-28 12:06:29 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
cout << "mongoperf" << endl;
|
|
|
|
|
|
|
|
|
|
if( argc > 1 ) {
|
2011-11-06 17:42:44 -05:00
|
|
|
cout <<
|
|
|
|
|
" usage:\n\n"
|
|
|
|
|
" mongoperf < myjsonconfigfile\n\n"
|
2011-10-31 18:22:38 -04:00
|
|
|
" json config doc fields:\n"
|
2011-11-06 17:42:44 -05:00
|
|
|
" nThreads:<n> number of threads\n"
|
2011-10-31 18:22:38 -04:00
|
|
|
" fileSizeMB:<n> test file size. if the file is small the heads will not move much\n"
|
2011-11-06 17:42:44 -05:00
|
|
|
" thus making the test not informative.\n"
|
|
|
|
|
" sleepMicros:<n> pause for sleepMicros/#threadsrunning between each operation\n"
|
2011-11-07 10:25:06 -05:00
|
|
|
" mmf:true do i/o's via memory mapped files\n"
|
2011-10-28 12:06:29 -04:00
|
|
|
<< endl;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string s = input;
|
|
|
|
|
str::stripTrailing(s, "\n\r\0x1a");
|
2011-10-31 18:22:38 -04:00
|
|
|
options = fromjson(s);
|
2011-10-28 12:06:29 -04:00
|
|
|
cout << "options:\n" << options.toString() << endl;
|
|
|
|
|
|
2011-10-31 18:22:38 -04:00
|
|
|
go();
|
2011-10-28 12:06:29 -04:00
|
|
|
#if 0
|
|
|
|
|
cout << "connecting to localhost..." << endl;
|
|
|
|
|
DBClientConnection c;
|
|
|
|
|
c.connect("localhost");
|
|
|
|
|
cout << "connected ok" << endl;
|
|
|
|
|
unsigned long long count = c.count("test.foo");
|
|
|
|
|
cout << "count of exiting documents in collection test.foo : " << count << endl;
|
|
|
|
|
|
|
|
|
|
bo o = BSON( "hello" << "world" );
|
|
|
|
|
c.insert("test.foo", o);
|
|
|
|
|
|
|
|
|
|
string e = c.getLastError();
|
|
|
|
|
if( !e.empty() ) {
|
|
|
|
|
cout << "insert #1 failed: " << e << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// make an index with a unique key constraint
|
|
|
|
|
c.ensureIndex("test.foo", BSON("hello"<<1), /*unique*/true);
|
|
|
|
|
|
|
|
|
|
c.insert("test.foo", o); // will cause a dup key error on "hello" field
|
|
|
|
|
cout << "we expect a dup key error here:" << endl;
|
|
|
|
|
cout << " " << c.getLastErrorDetailed().toString() << endl;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
catch(DBException& e) {
|
|
|
|
|
cout << "caught DBException " << e.toString() << endl;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|