diff options
author | dalyd <david.daly@mongodb.com> | 2015-05-08 09:43:43 -0400 |
---|---|---|
committer | dalyd <david.daly@mongodb.com> | 2015-05-29 11:33:26 -0400 |
commit | 83316787e7e7515a3222dd2cbf5acd8356d01284 (patch) | |
tree | 446a0bd5641ce2425f004e122a3b259c2561d9c8 | |
parent | dd81a3bec958d1d78913630fd4a3523170fd23db (diff) | |
download | mongo-83316787e7e7515a3222dd2cbf5acd8356d01284.tar.gz |
SERVER-13237: benchRun should use a thread-safe random number generator
(cherry picked from commit acc1ebc194ab01f81750a4e60dc78a3a9bac650f)
-rw-r--r-- | src/mongo/scripting/bson_template_evaluator.cpp | 11 | ||||
-rw-r--r-- | src/mongo/scripting/bson_template_evaluator.h | 9 | ||||
-rw-r--r-- | src/mongo/scripting/bson_template_evaluator_test.cpp | 20 | ||||
-rw-r--r-- | src/mongo/shell/bench.cpp | 17 | ||||
-rw-r--r-- | src/mongo/shell/bench.h | 7 |
5 files changed, 42 insertions, 22 deletions
diff --git a/src/mongo/scripting/bson_template_evaluator.cpp b/src/mongo/scripting/bson_template_evaluator.cpp index 8b6e42756a2..634a478b613 100644 --- a/src/mongo/scripting/bson_template_evaluator.cpp +++ b/src/mongo/scripting/bson_template_evaluator.cpp @@ -48,7 +48,7 @@ namespace mongo { addOperator("VARIABLE", &BsonTemplateEvaluator::evalVariable); } - BsonTemplateEvaluator::BsonTemplateEvaluator() : _id(0) { + BsonTemplateEvaluator::BsonTemplateEvaluator(int64_t seed) : _id(0), rng(seed) { initializeEvaluator(); } @@ -169,7 +169,8 @@ namespace mongo { const int max = range["1"].numberInt(); if (max <= min) return StatusOpEvaluationError; - int randomNum = min + (rand() % (max - min)); + // range of max-min + int randomNum = min + (btl->rng.nextInt32() % (max - min)); if (range.nFields() == 3) { if (!range[2].isNumber()) return StatusOpEvaluationError; @@ -192,7 +193,7 @@ namespace mongo { const int max = range["1"].numberInt(); if (max <= min) return StatusOpEvaluationError; - int randomNum = min + (rand() % (max - min)); + int randomNum = min + (btl->rng.nextInt32() % (max - min)); randomNum += ((max - min) * btl->_id); out.append(fieldName, randomNum); return StatusSuccess; @@ -269,11 +270,11 @@ namespace mongo { "0123456789+/"; static const size_t alphaNumLength = sizeof(alphanum) - 1; BOOST_STATIC_ASSERT(alphaNumLength == 64); - unsigned currentRand = 0; + int32_t currentRand = 0; std::string str; for (int i = 0; i < length; ++i, currentRand >>= 6) { if (i % 5 == 0) - currentRand = rand(); + currentRand = btl->rng.nextInt32(); str.push_back(alphanum[currentRand % alphaNumLength]); } out.append(fieldName, str); diff --git a/src/mongo/scripting/bson_template_evaluator.h b/src/mongo/scripting/bson_template_evaluator.h index d5fe8353524..67c3c5bf7d0 100644 --- a/src/mongo/scripting/bson_template_evaluator.h +++ b/src/mongo/scripting/bson_template_evaluator.h @@ -50,6 +50,7 @@ #include "mongo/db/jsobj.h" #include "mongo/stdx/functional.h" +#include "mongo/platform/random.h" namespace mongo { @@ -97,7 +98,10 @@ namespace mongo { typedef stdx::function< Status (BsonTemplateEvaluator* btl, const char* fieldName, const BSONObj& in, BSONObjBuilder& builder) > OperatorFn; - BsonTemplateEvaluator(); + /* + * @params seed : Random seed to be used when generating random data + */ + BsonTemplateEvaluator(int64_t seed); ~BsonTemplateEvaluator(); /** @@ -235,6 +239,9 @@ namespace mongo { static Status evalVariable(BsonTemplateEvaluator* btl, const char* fieldName, const BSONObj& in, BSONObjBuilder& out); + // Per object pseudo random number generator + PseudoRandom rng; + }; } // end namespace diff --git a/src/mongo/scripting/bson_template_evaluator_test.cpp b/src/mongo/scripting/bson_template_evaluator_test.cpp index 5321ee02b7a..c589617f34f 100644 --- a/src/mongo/scripting/bson_template_evaluator_test.cpp +++ b/src/mongo/scripting/bson_template_evaluator_test.cpp @@ -68,7 +68,7 @@ namespace mongo { TEST(BSONTemplateEvaluatorTest, RAND_INT) { - BsonTemplateEvaluator t; + BsonTemplateEvaluator t(1234567); int randValue1, randValue2; common_rand_tests("#RAND_INT", &t); @@ -158,7 +158,7 @@ namespace mongo { TEST(BSONTemplateEvaluatorTest, RAND_INT_PLUS_THREAD) { - BsonTemplateEvaluator t; + BsonTemplateEvaluator t(2345678); t.setId(1); int randValue1, randValue2; @@ -248,7 +248,7 @@ namespace mongo { ASSERT_LESS_THAN_OR_EQUALS(randValue1, 10); // Test success with a single element for a zero _id - BsonTemplateEvaluator t2; + BsonTemplateEvaluator t2(3456789); t2.setId(0); BSONObjBuilder builder13; @@ -264,7 +264,7 @@ namespace mongo { TEST(BSONTemplateEvaluatorTest, SEQ_INT) { - boost::scoped_ptr<BsonTemplateEvaluator> t(new BsonTemplateEvaluator()); + boost::scoped_ptr<BsonTemplateEvaluator> t(new BsonTemplateEvaluator(131415)); BSONObj seqObj; BSONObj expectedObj; @@ -401,7 +401,7 @@ namespace mongo { TEST(BSONTemplateEvaluatorTest, RAND_STRING) { - BsonTemplateEvaluator t; + BsonTemplateEvaluator t(4567890); // Test failure when the arguments to RAND_STRING is not an integer BSONObjBuilder builder1; @@ -506,7 +506,7 @@ namespace mongo { TEST(BSONTemplateEvaluatorTest, CONCAT) { - BsonTemplateEvaluator t; + BsonTemplateEvaluator t(5678901); // Test failure when the arguments to #CONCAT has only one argument BSONObjBuilder builder1; @@ -561,7 +561,7 @@ namespace mongo { TEST(BSONTemplateEvaluatorTest, OID) { - BsonTemplateEvaluator t; + BsonTemplateEvaluator t(6789012); BSONObj oidObj = BSON( "#OID" << 1 ); // Error: field must be "_id" @@ -578,7 +578,7 @@ namespace mongo { TEST(BSONTemplateEvaluatorTest, COMBINED_OPERATORS) { - BsonTemplateEvaluator t; + BsonTemplateEvaluator t(7890123); BSONObj randIntObj = BSON( "#RAND_INT" << BSON_ARRAY( 0 << 5 ) ); BSONObj randStrObj = BSON( "#RAND_STRING" << BSON_ARRAY(5) ); @@ -612,7 +612,7 @@ namespace mongo { // Test #VARIABLE TEST(BSONTemplateEvaluatorTest, VARIABLE) { - BsonTemplateEvaluator t; + BsonTemplateEvaluator t(8901234); int value1; // Test failure when the variable has not been set @@ -638,7 +638,7 @@ namespace mongo { // Test template recursion and other general features TEST(BSONTemplateEvaluatorTest, NESTING) { - BsonTemplateEvaluator t; + BsonTemplateEvaluator t(8901234); int randValue1, randValue2; // Test failure when operators are arbitrarily nested diff --git a/src/mongo/shell/bench.cpp b/src/mongo/shell/bench.cpp index 069af0ee7c7..87b3da10a36 100644 --- a/src/mongo/shell/bench.cpp +++ b/src/mongo/shell/bench.cpp @@ -156,6 +156,7 @@ namespace mongo { throwGLE = false; breakOnTrap = true; + randomSeed = 1314159265358979323; } BenchRunConfig *BenchRunConfig::createFromBson( const BSONObj &args ) { @@ -178,6 +179,8 @@ namespace mongo { if ( args["parallel"].isNumber() ) this->parallel = args["parallel"].numberInt(); + if ( args["randomSeed"].isNumber() ) + this->randomSeed = args["randomSeed"].numberInt(); if ( args["seconds"].isNumber() ) this->seconds = args["seconds"].number(); if ( ! args["hideResults"].eoo() ) @@ -320,8 +323,9 @@ namespace mongo { return b.obj(); } - BenchRunWorker::BenchRunWorker(size_t id, const BenchRunConfig *config, BenchRunState *brState) - : _id(id), _config(config), _brState(brState) { + BenchRunWorker::BenchRunWorker(size_t id, const BenchRunConfig *config, BenchRunState *brState, + int64_t randomSeed) + : _id(id), _config(config), _brState(brState), _randomSeed(randomSeed) { } BenchRunWorker::~BenchRunWorker() {} @@ -341,7 +345,7 @@ namespace mongo { long long count = 0; mongo::Timer timer; - BsonTemplateEvaluator bsonTemplateEvaluator; + BsonTemplateEvaluator bsonTemplateEvaluator(_randomSeed); invariant(bsonTemplateEvaluator.setId(_id) == BsonTemplateEvaluator::StatusSuccess); if (_config->username != "") { @@ -786,8 +790,11 @@ namespace mongo { } // Start threads - for ( unsigned i = 0; i < _config->parallel; i++ ) { - BenchRunWorker *worker = new BenchRunWorker(i, _config.get(), &_brState); + for ( int64_t i = 0; i < _config->parallel; i++ ) { + // Make a unique random seed for the worker. + int64_t seed = _config->randomSeed + i; + BenchRunWorker *worker = new BenchRunWorker(i, _config.get(), + &_brState, seed); worker->start(); _workers.push_back(worker); } diff --git a/src/mongo/shell/bench.h b/src/mongo/shell/bench.h index f7a58799465..280d7c1399d 100644 --- a/src/mongo/shell/bench.h +++ b/src/mongo/shell/bench.h @@ -102,6 +102,9 @@ namespace mongo { */ double seconds; + /// Base random seed for threads + int64_t randomSeed; + bool hideResults; bool handleErrors; bool hideErrors; @@ -325,7 +328,8 @@ namespace mongo { * * "id" is a positive integer which should uniquely identify the worker. */ - BenchRunWorker(size_t id, const BenchRunConfig *config, BenchRunState *brState); + BenchRunWorker(size_t id, const BenchRunConfig *config, + BenchRunState *brState, int64_t randomSeed); ~BenchRunWorker(); /** @@ -355,6 +359,7 @@ namespace mongo { const BenchRunConfig *_config; BenchRunState *_brState; BenchRunStats _stats; + int64_t _randomSeed; }; /** |