summaryrefslogtreecommitdiff
path: root/jstests/perf
diff options
context:
space:
mode:
authorShaun Verch <shaun.verch@10gen.com>2013-02-25 17:53:14 -0800
committerShaun Verch <shaun.verch@10gen.com>2013-04-11 14:09:55 -0700
commitb7245d22bd7699400196e1d077bfdc3996b37bd9 (patch)
treebb998997bb66cc9fb97a560d7990a26417fd8a5e /jstests/perf
parent359b0b8c25e76b18bf6a366d9d6d9115f5a26fcc (diff)
downloadmongo-b7245d22bd7699400196e1d077bfdc3996b37bd9.tar.gz
SERVER-7760 Added parallel mapReduce test for v8
Diffstat (limited to 'jstests/perf')
-rw-r--r--jstests/perf/v8_mapreduce.js119
1 files changed, 119 insertions, 0 deletions
diff --git a/jstests/perf/v8_mapreduce.js b/jstests/perf/v8_mapreduce.js
new file mode 100644
index 00000000000..1c66f26d5b8
--- /dev/null
+++ b/jstests/perf/v8_mapreduce.js
@@ -0,0 +1,119 @@
+// Testing parallelism of mapReduce in V8
+
+// Our server and client need to be running V8 and the host we are running on needs at least two
+// cores. Update this if you are testing more than three threads in parallel.
+if (/V8/.test(interpreterVersion()) &&
+ db.runCommand({buildinfo:1}).javascriptEngine == "V8" &&
+ db.hostInfo().system.numCores >= 2) {
+
+ // function timeSingleThread
+ // Description: Gathers data about how long it takes to run a given job
+ // Args: job - job to run
+ // tid - thread id passed as an argument to the job, default 0
+ // Returns: { threadStart : <time job started> , threadEnd : <time job completed> }
+ var timeSingleThread = function (job, tid) {
+ var tid = tid || 0;
+ var threadStart = new Date();
+ job(tid);
+ return { "threadStart" : threadStart , "threadEnd" : new Date() };
+ };
+
+ // function timeMultipleThreads
+ // Description: Gathers data about how long it takes to run a given job in multiple threads.
+ // Args: job - job to run in each thread
+ // nthreads - number of threads to spawn
+ // stagger - delay between each thread spawned in milliseconds
+ // Returns: Array with one entry for each thread of the form:
+ // [ { threadStart : <time elapsed before thread started work> ,
+ // threadEnd : <time elapsed before thread completed work> } ,
+ // ...
+ // ]
+ var timeMultipleThreads = function (job, nthreads, stagger) {
+ var i = 0;
+ var threads = [];
+
+ for (i = 0; i < nthreads; ++i) {
+ threads[i] = new Thread(timeSingleThread, job, i);
+ }
+
+ // Our "reference time" that all threads agree on
+ var referenceTime = new Date();
+
+ for (i = 0; i < nthreads; ++i) {
+ if (stagger && i > 0) {
+ sleep(stagger);
+ }
+ threads[i].start();
+ }
+
+ var threadTimes = [];
+ for (i = 0; i < nthreads; ++i) {
+ var returnData = threads[i].returnData();
+ threadTimes[i] = {};
+ threadTimes[i].threadStart = returnData.threadStart - referenceTime;
+ threadTimes[i].threadEnd = returnData.threadEnd - referenceTime;
+ }
+
+ return threadTimes;
+ };
+
+ // Display and analysis helper functions
+
+ var getLastCompletion = function (threadTimes) {
+ var lastCompletion = 0;
+ for (var i = 0; i < threadTimes.length; i++) {
+ lastCompletion = Math.max(lastCompletion, threadTimes[i].threadEnd);
+ }
+ return lastCompletion;
+ }
+
+ // Functions we are performance testing
+
+ db.v8_parallel_mr_src.drop();
+
+ for (j=0; j<100; j++) for (i=0; i<512; i++){ db.v8_parallel_mr_src.save({j:j, i:i})}
+
+ db.getLastError();
+
+ var mrWorkFunction = function () {
+
+ function verifyOutput(out) {
+ //printjson(out);
+ assert.eq(out.counts.input, 51200, "input count is wrong");
+ assert.eq(out.counts.emit, 51200, "emit count is wrong");
+ assert.gt(out.counts.reduce, 99, "reduce count is wrong");
+ assert.eq(out.counts.output, 512, "output count is wrong");
+ }
+
+ function map() {
+ if (this.j % 2 == 0) {
+ emit(this.i, this.j*this.j);
+ }
+ else {
+ emit(this.i, this.j+this.j);
+ }
+ }
+
+ function reduce(key, values) {
+ values_halved = values.map(function (value) {
+ return value / 2
+ });
+ values_halved_sum = Array.sum(values_halved);
+ return values_halved_sum;
+ }
+
+ var out = db.v8_parallel_mr_src.mapReduce(map, reduce, { out : "v8_parallel_mr_out" });
+ verifyOutput(out);
+ };
+
+ var oneMapReduce = getLastCompletion(timeMultipleThreads(mrWorkFunction, 1));
+ var twoMapReduce = getLastCompletion(timeMultipleThreads(mrWorkFunction, 2));
+ var threeMapReduce = getLastCompletion(timeMultipleThreads(mrWorkFunction, 3));
+
+ printjson("One map reduce job: " + oneMapReduce);
+ printjson("Two map reduce jobs: " + twoMapReduce);
+ printjson("Three map reduce jobs: " + threeMapReduce);
+
+ assert(oneMapReduce * 1.75 > twoMapReduce);
+ assert(oneMapReduce * 2.5 > threeMapReduce);
+}