/** @file bench.cpp */
/*
* Copyright (C) 2010 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 .
*/
#include "pch.h"
#include "engine.h"
#include "../util/md5.hpp"
#include "../util/version.h"
#include "../client/dbclient.h"
#include "../client/connpool.h"
// ---------------------------------
// ---- benchmarking system --------
// ---------------------------------
namespace mongo {
struct BenchRunConfig {
BenchRunConfig() {
host = "localhost";
db = "test";
parallel = 1;
seconds = 1;
active = true;
threadsReady = 0;
error = false;
}
string host;
string db;
unsigned parallel;
double seconds;
BSONObj ops;
bool active; // true at starts, gets set to false when should stop
AtomicUInt threadsReady;
bool error;
};
static void benchThread( BenchRunConfig * config ) {
ScopedDbConnection conn( config->host );
config->threadsReady++;
while ( config->active ) {
BSONObjIterator i( config->ops );
while ( i.more() ) {
BSONElement e = i.next();
string ns = e["ns"].String();
string op = e["op"].String();
if ( op == "findOne" ) {
conn->findOne( ns , e["query"].Obj() );
}
else if ( op == "update" ) {
conn->update( ns , e["query"].Obj() , e["update"].Obj() );
}
else {
log() << "don't understand op: " << op << endl;
config->error = true;
return;
}
}
}
conn.done();
}
/**
* benchRun( { ops : [] , host : XXX , db : XXXX , parallel : 5 , seconds : 5 }
*/
BSONObj benchRun( const BSONObj& argsFake, void* data ) {
assert( argsFake.firstElement().isABSONObj() );
BSONObj args = argsFake.firstElement().Obj();
// setup
BenchRunConfig config;
if ( args["host"].type() == String )
config.host = args["host"].String();
if ( args["db"].type() == String )
config.db = args["db"].String();
if ( args["parallel"].isNumber() )
config.parallel = args["parallel"].numberInt();
if ( args["seconds"].isNumber() )
config.seconds = args["seconds"].number();
config.ops = args["ops"].Obj();
// execute
ScopedDbConnection conn( config.host );
// start threads
vector all;
for ( unsigned i=0; isimpleCommand( "admin" , &before , "serverStatus" );
sleepmillis( (int)(1000.0 * config.seconds) );
BSONObj after;
conn->simpleCommand( "admin" , &after , "serverStatus" );
conn.done();
config.active = false;
for ( unsigned i=0; ijoin();
if ( config.error )
return BSON( "err" << 1 );
// compute actual ops/sec
before = before["opcounters"].Obj();
after = after["opcounters"].Obj();
BSONObjBuilder buf;
buf.append( "note" , "values per second" );
{
BSONObjIterator i( after );
while ( i.more() ) {
BSONElement e = i.next();
double x = e.number();
x = x - before[e.fieldName()].number();
buf.append( e.fieldName() , x / config.seconds );
}
}
BSONObj zoo = buf.obj();
return BSON( "" << zoo );
}
void installBenchmarkSystem( Scope& scope ) {
scope.injectNative( "benchRun" , benchRun );
}
}