summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordalyd <david.daly@mongodb.com>2015-05-08 09:43:43 -0400
committerdalyd <david.daly@mongodb.com>2015-05-28 13:22:57 -0400
commitacc1ebc194ab01f81750a4e60dc78a3a9bac650f (patch)
tree1aeff03b58e60d4d0d998657c19b2f1a9dc3ef68
parent7d526bbc47681fd297d38cdc577a9a7d710f7a99 (diff)
downloadmongo-acc1ebc194ab01f81750a4e60dc78a3a9bac650f.tar.gz
SERVER-13237: benchRun should use a thread-safe random number generator
-rw-r--r--src/mongo/scripting/bson_template_evaluator.cpp11
-rw-r--r--src/mongo/scripting/bson_template_evaluator.h9
-rw-r--r--src/mongo/scripting/bson_template_evaluator_test.cpp20
-rw-r--r--src/mongo/shell/bench.cpp17
-rw-r--r--src/mongo/shell/bench.h7
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 ae4fe3e0e59..9f016a5b65f 100644
--- a/src/mongo/shell/bench.cpp
+++ b/src/mongo/shell/bench.cpp
@@ -155,6 +155,7 @@ namespace mongo {
throwGLE = false;
breakOnTrap = true;
+ randomSeed = 1314159265358979323;
}
BenchRunConfig *BenchRunConfig::createFromBson( const BSONObj &args ) {
@@ -177,6 +178,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 != "") {
@@ -785,8 +789,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;
};
/**