/** @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 ); } }