Mythbusting: Understanding How We Measure Performance at MongoDB

70
VP, Engineering, MongoDB Andrew Erlichson #MongoDBDays Mythbusting: Understanding How We Measure the Performance of MongoDB

description

Benchmarking, benchmarking, benchmarking. We all do it, mostly it tells us what we want to hear but often hides a mountain of misinformation. In this talk we will walk through the pitfalls that you might find yourself in by looking at some examples where things go wrong. We will then walk through how MongoDB performance is measured, the processes and methodology and ways to present and look at the information.

Transcript of Mythbusting: Understanding How We Measure Performance at MongoDB

Page 1: Mythbusting: Understanding How We Measure Performance at MongoDB

VP, Engineering, MongoDB

Andrew Erlichson

#MongoDBDays

Mythbusting: Understanding How We Measure the Performance of MongoDB

Page 2: Mythbusting: Understanding How We Measure Performance at MongoDB

Before we start…

• We are going to look a lot at– C++ kernel code– Java benchmarks– JavaScript tests

• And lots of charts

• And its going to be awesome!

Page 3: Mythbusting: Understanding How We Measure Performance at MongoDB

Goals of Benchmarking

– You have an idea– It must be tested– Others must be able

to reproduce your work.

– Explanations that contribute to knowledge are key.

– Should have practical applications

Academia

Page 4: Mythbusting: Understanding How We Measure Performance at MongoDB

Industry Benchmarketing

• Prove you are faster than the competition

• Emphasize your best attributes

• Repeatable

• Explanations

Page 5: Mythbusting: Understanding How We Measure Performance at MongoDB

Industry Benchmarketing

• Prove you are faster than the competition

• Emphasize your best attributes

• Repeatable*

• Explanations*

*OPTIONAL

Page 6: Mythbusting: Understanding How We Measure Performance at MongoDB

Goals of Internal Benchmarking

• Always be improving

• Understand our bottlenecks

• Main customer is engineering

• Explanations are somewhat important.

Page 7: Mythbusting: Understanding How We Measure Performance at MongoDB

Overview – Internal Benchmarking

• Some common traps

• Performance measurement & diagnosis

• What's next

Page 8: Mythbusting: Understanding How We Measure Performance at MongoDB

Part OneSome Common Traps

Page 9: Mythbusting: Understanding How We Measure Performance at MongoDB

long startTime = System.currentTimeMillis();

for (int roundNum = 0; roundNum < numRounds; roundNum++) {

for (int i = 0; i < documentsPerInsert; i++) {

id++;

BasicDBObject doc = new BasicDBObject();

doc.put("_id",id);

doc.put("k",rand.nextInt(numMaxInserts)+1);

String cVal = "…"

doc.put("c",cVal);

String padVal = "…";

doc.put("pad",padVal);

aDocs[i]=doc;

}

coll.insert(aDocs);

numInserts += documentsPerInsert;

globalInserts.addAndGet(documentsPerInsert);

}

long endTime = System.currentTimeMillis();

#1 Time taken to Insert x Documents

Page 10: Mythbusting: Understanding How We Measure Performance at MongoDB

long startTime = System.currentTimeMillis();

for (int roundNum = 0; roundNum < numRounds; roundNum++) {

for (int i = 0; i < documentsPerInsert; i++) {

id++;

BasicDBObject doc = new BasicDBObject();

doc.put("_id",id);

doc.put("k",rand.nextInt(numMaxInserts)+1);

String cVal = "…"

doc.put("c",cVal);

String padVal = "…";

doc.put("pad",padVal);

aDocs[i]=doc;

}

coll.insert(aDocs);

numInserts += documentsPerInsert;

globalInserts.addAndGet(documentsPerInsert);

}

long endTime = System.currentTimeMillis();

#1 Time taken to Insert x Documents

Page 11: Mythbusting: Understanding How We Measure Performance at MongoDB

long startTime = System.currentTimeMillis();

for (int roundNum = 0; roundNum < numRounds; roundNum++) {

for (int i = 0; i < documentsPerInsert; i++) {

id++;

BasicDBObject doc = new BasicDBObject();

doc.put("_id",id);

doc.put("k",rand.nextInt(numMaxInserts)+1);

String cVal = "…"

doc.put("c",cVal);

String padVal = "…";

doc.put("pad",padVal);

aDocs[i]=doc;

}

coll.insert(aDocs);

numInserts += documentsPerInsert;

globalInserts.addAndGet(documentsPerInsert);

}

long endTime = System.currentTimeMillis();

#1 Time taken to Insert x Documents

Page 12: Mythbusting: Understanding How We Measure Performance at MongoDB

long startTime = System.currentTimeMillis();

for (int roundNum = 0; roundNum < numRounds; roundNum++) {

for (int i = 0; i < documentsPerInsert; i++) {

id++;

BasicDBObject doc = new BasicDBObject();

doc.put("_id",id);

doc.put("k",rand.nextInt(numMaxInserts)+1);

String cVal = "…"

doc.put("c",cVal);

String padVal = "…";

doc.put("pad",padVal);

aDocs[i]=doc;

}

coll.insert(aDocs);

numInserts += documentsPerInsert;

globalInserts.addAndGet(documentsPerInsert);

}

long endTime = System.currentTimeMillis();

#1 Time taken to Insert x Documents

Page 13: Mythbusting: Understanding How We Measure Performance at MongoDB

long startTime = System.currentTimeMillis();

for (int roundNum = 0; roundNum < numRounds; roundNum++) {

for (int i = 0; i < documentsPerInsert; i++) {

id++;

BasicDBObject doc = new BasicDBObject();

doc.put("_id",id);

doc.put("k",rand.nextInt(numMaxInserts)+1);

String cVal = "…"

doc.put("c",cVal);

String padVal = "…";

doc.put("pad",padVal);

aDocs[i]=doc;

}

coll.insert(aDocs);

numInserts += documentsPerInsert;

globalInserts.addAndGet(documentsPerInsert);

}

long endTime = System.currentTimeMillis();

#1 Time taken to Insert x Documents

Page 14: Mythbusting: Understanding How We Measure Performance at MongoDB

long startTime = System.currentTimeMillis();

for (int roundNum = 0; roundNum < numRounds; roundNum++) {

for (int i = 0; i < documentsPerInsert; i++) {

id++;

BasicDBObject doc = new BasicDBObject();

doc.put("_id",id);

doc.put("k",rand.nextInt(numMaxInserts)+1);

String cVal = "…"

doc.put("c",cVal);

String padVal = "…";

doc.put("pad",padVal);

aDocs[i]=doc;

}

coll.insert(aDocs);

numInserts += documentsPerInsert;

globalInserts.addAndGet(documentsPerInsert);

}

long endTime = System.currentTimeMillis();

So that looks ok, right?

Page 15: Mythbusting: Understanding How We Measure Performance at MongoDB

long startTime = System.currentTimeMillis();

for (int roundNum = 0; roundNum < numRounds; roundNum++) {

for (int i = 0; i < documentsPerInsert; i++) {

id++;

BasicDBObject doc = new BasicDBObject();

doc.put("_id",id);

doc.put("k",rand.nextInt(numMaxInserts)+1);

String cVal = "…"

doc.put("c",cVal);

String padVal = "…";

doc.put("pad",padVal);

aDocs[i]=doc;

}

coll.insert(aDocs);

numInserts += documentsPerInsert;

globalInserts.addAndGet(documentsPerInsert);

}

long endTime = System.currentTimeMillis();

What are else you measuring?

Object creation and GC management?

Page 16: Mythbusting: Understanding How We Measure Performance at MongoDB

long startTime = System.currentTimeMillis();

for (int roundNum = 0; roundNum < numRounds; roundNum++) {

for (int i = 0; i < documentsPerInsert; i++) {

id++;

BasicDBObject doc = new BasicDBObject();

doc.put("_id",id);

doc.put("k",rand.nextInt(numMaxInserts)+1);

String cVal = "…"

doc.put("c",cVal);

String padVal = "…";

doc.put("pad",padVal);

aDocs[i]=doc;

}

coll.insert(aDocs);

numInserts += documentsPerInsert;

globalInserts.addAndGet(documentsPerInsert);

}

long endTime = System.currentTimeMillis();

What are else you measuring?

Thread contention on nextInt()?

Object creation and GC management?

Page 17: Mythbusting: Understanding How We Measure Performance at MongoDB

long startTime = System.currentTimeMillis();

for (int roundNum = 0; roundNum < numRounds; roundNum++) {

for (int i = 0; i < documentsPerInsert; i++) {

id++;

BasicDBObject doc = new BasicDBObject();

doc.put("_id",id);

doc.put("k",rand.nextInt(numMaxInserts)+1);

String cVal = "…"

doc.put("c",cVal);

String padVal = "…";

doc.put("pad",padVal);

aDocs[i]=doc;

}

coll.insert(aDocs);

numInserts += documentsPerInsert;

globalInserts.addAndGet(documentsPerInsert);

}

long endTime = System.currentTimeMillis();

What are else you measuring?

Time to synthesize data?

Object creation and GC management?

Thread contention on nextInt()?

Page 18: Mythbusting: Understanding How We Measure Performance at MongoDB

long startTime = System.currentTimeMillis();

for (int roundNum = 0; roundNum < numRounds; roundNum++) {

for (int i = 0; i < documentsPerInsert; i++) {

id++;

BasicDBObject doc = new BasicDBObject();

doc.put("_id",id);

doc.put("k",rand.nextInt(numMaxInserts)+1);

String cVal = "…"

doc.put("c",cVal);

String padVal = "…";

doc.put("pad",padVal);

aDocs[i]=doc;

}

coll.insert(aDocs);

numInserts += documentsPerInsert;

globalInserts.addAndGet(documentsPerInsert);

}

long endTime = System.currentTimeMillis();

What are else you measuring?

Object creation and GC management?

Thread contention on addAndGet()?

Thread contention on nextInt()?

Time to synthesize data?

Page 19: Mythbusting: Understanding How We Measure Performance at MongoDB

long startTime = System.currentTimeMillis();

for (int roundNum = 0; roundNum < numRounds; roundNum++) {

for (int i = 0; i < documentsPerInsert; i++) {

id++;

BasicDBObject doc = new BasicDBObject();

doc.put("_id",id);

doc.put("k",rand.nextInt(numMaxInserts)+1);

String cVal = "…"

doc.put("c",cVal);

String padVal = "…";

doc.put("pad",padVal);

aDocs[i]=doc;

}

coll.insert(aDocs);

numInserts += documentsPerInsert;

globalInserts.addAndGet(documentsPerInsert);

}

long endTime = System.currentTimeMillis();

What are else you measuring?

Object creation and GC management?

Clock resolution?

Thread contention on nextInt()?

Time to synthesize data?

Thread contention on addAndGet()?

Page 20: Mythbusting: Understanding How We Measure Performance at MongoDB

// Pre Create the Object outside the Loop

BasicDBObject[] aDocs = new BasicDBObject[documentsPerInsert];

for (int i=0; i < documentsPerInsert; i++) {

BasicDBObject doc = new BasicDBObject();

String cVal = "…";

doc.put("c",cVal);

String padVal = "…";

doc.put("pad",padVal);

aDocs[i] = doc;

}

Solution: Pre-Create the objects

Pre-create non varying data outside the timing loop

Alternative

• Pre-create the data in a file; load from file

Page 21: Mythbusting: Understanding How We Measure Performance at MongoDB

// Use ThreadLocalRandom generator or an instance of java.util.Random per thread

java.util.concurrent.ThreadLocalRandom rand;

for (long roundNum = 0; roundNum < numRounds; roundNum++) {

for (int i = 0; i < documentsPerInsert; i++) {

id++;

doc = aDocs[i];

doc.put("_id",id);

doc.put("k", nextInt(rand, numMaxInserts)+1);

}

coll.insert(aDocs);

numInserts += documentsPerInsert;

}

// Maintain count outside the loop

globalInserts.addAndGet(documentsPerInsert * roundNum);

Solution: Remove contention

Remove contention nextInt() by making Thread local

Page 22: Mythbusting: Understanding How We Measure Performance at MongoDB

// Use ThreadLocalRandom generator or an instance of java.util.Random per thread

java.util.concurrent.ThreadLocalRandom rand;

for (long roundNum = 0; roundNum < numRounds; roundNum++) {

for (int i = 0; i < documentsPerInsert; i++) {

id++;

doc = aDocs[i];

doc.put("_id",id);

doc.put("k", nextInt(rand, numMaxInserts)+1);

}

coll.insert(aDocs);

numInserts += documentsPerInsert;

}

// Maintain count outside the loop

globalInserts.addAndGet(documentsPerInsert * roundNum);

Solution: Remove contention

Remove contention on addAndGet()

Remove contention nextInt() by making Thread local

Page 23: Mythbusting: Understanding How We Measure Performance at MongoDB

long startTime = System.currentTimeMillis();

long endTime = System.currentTimeMillis();

long startTime = System.nanoTime();

long endTime = System.nanoTime() - startTime;

Solution: Timer resolution

"resolution is at least as good as that of currentTimeMillis()"

"granularity of the value depends on the underlying operating system and may be larger"

Source

• http://docs.oracle.com/javase/7/docs/api/java/lang/System.html

Page 24: Mythbusting: Understanding How We Measure Performance at MongoDB

General Principal #1Know what you are measuring

Page 25: Mythbusting: Understanding How We Measure Performance at MongoDB

BasicDBObject doc = new BasicDBObject();

doc.put("v", str); // str is a 2k string

for (int i=0; i < 1000; i++) {

doc.put("_id",i); coll.insert(doc);

}

BasicDBObject predicate = new BasicDBObject();

long startTime = System.currentTimeMillis();

DBCursor cur = coll.find(predicate);

DBObject foundObj;

while (cur.hasNext()) {

foundObj = cur.next();

}

long endTime = System.currentTimeMillis();

#2 Response time to return all results

Page 26: Mythbusting: Understanding How We Measure Performance at MongoDB

BasicDBObject doc = new BasicDBObject();

doc.put("v", str); // str is a 2k string

for (int i=0; i < 1000; i++) {

doc.put("_id",i); coll.insert(doc);

}

BasicDBObject predicate = new BasicDBObject();

long startTime = System.currentTimeMillis();

DBCursor cur = coll.find(predicate);

DBObject foundObj;

while (cur.hasNext()) {

foundObj = cur.next();

}

long endTime = System.currentTimeMillis();

#2 Response time to return all results

Page 27: Mythbusting: Understanding How We Measure Performance at MongoDB

BasicDBObject doc = new BasicDBObject();

doc.put("v", str); // str is a 2k string

for (int i=0; i < 1000; i++) {

doc.put("_id",i); coll.insert(doc);

}

BasicDBObject predicate = new BasicDBObject();

long startTime = System.currentTimeMillis();

DBCursor cur = coll.find(predicate);

DBObject foundObj;

while (cur.hasNext()) {

foundObj = cur.next();

}

long endTime = System.currentTimeMillis();

#2 Response time to return all results

Page 28: Mythbusting: Understanding How We Measure Performance at MongoDB

BasicDBObject doc = new BasicDBObject();

doc.put("v", str); // str is a 2k string

for (int i=0; i < 1000; i++) {

doc.put("_id",i); coll.insert(doc);

}

BasicDBObject predicate = new BasicDBObject();

long startTime = System.currentTimeMillis();

DBCursor cur = coll.find(predicate);

DBObject foundObj;

while (cur.hasNext()) {

foundObj = cur.next();

}

long endTime = System.currentTimeMillis();

#2 Response time to return all results

Page 29: Mythbusting: Understanding How We Measure Performance at MongoDB

BasicDBObject doc = new BasicDBObject();

doc.put("v", str); // str is a 2k string

for (int i=0; i < 1000; i++) {

doc.put("_id",i); coll.insert(doc);

}

BasicDBObject predicate = new BasicDBObject();

long startTime = System.currentTimeMillis();

DBCursor cur = coll.find(predicate);

DBObject foundObj;

while (cur.hasNext()) {

foundObj = cur.next();

}

long endTime = System.currentTimeMillis();

So that looks ok, right?

Page 30: Mythbusting: Understanding How We Measure Performance at MongoDB

BasicDBObject doc = new BasicDBObject();

doc.put("v", str); // str is a 2k string

for (int i=0; i < 1000; i++) {

doc.put("_id",i); coll.insert(doc);

}

BasicDBObject predicate = new BasicDBObject();

long startTime = System.currentTimeMillis();

DBCursor cur = coll.find(predicate);

DBObject foundObj;

while (cur.hasNext()) {

foundObj = cur.next();

}

long endTime = System.currentTimeMillis();

What else are you measuring?

Each doc is is 4080 bytes on disk with powerOf2Sizes

Page 31: Mythbusting: Understanding How We Measure Performance at MongoDB

BasicDBObject doc = new BasicDBObject();

doc.put("v", str); // str is a 2k string

for (int i=0; i < 1000; i++) {

doc.put("_id",i); coll.insert(doc);

}

BasicDBObject predicate = new BasicDBObject();

long startTime = System.currentTimeMillis();

DBCursor cur = coll.find(predicate);

DBObject foundObj;

while (cur.hasNext()) {

foundObj = cur.next();

}

long endTime = System.currentTimeMillis();

What else are you measuring?

Each doc is is 4080 bytes on disk with powerOf2Sizes

Unrestricted predicate?

Page 32: Mythbusting: Understanding How We Measure Performance at MongoDB

BasicDBObject doc = new BasicDBObject();

doc.put("v", str); // str is a 2k string

for (int i=0; i < 1000; i++) {

doc.put("_id",i); coll.insert(doc);

}

BasicDBObject predicate = new BasicDBObject();

long startTime = System.currentTimeMillis();

DBCursor cur = coll.find(predicate);

DBObject foundObj;

while (cur.hasNext()) {

foundObj = cur.next();

}

long endTime = System.currentTimeMillis();

What else are you measuring?

Each doc is is 4080 bytes on disk with powerOf2Sizes

Measuring• Time to parse &

execute query• Time to retrieve all

documentBut also• Cost of shipping

~4MB data through network stack

Unrestricted predicate?

Page 33: Mythbusting: Understanding How We Measure Performance at MongoDB

BasicDBObject predicate = new BasicDBObject();

predicate.put("_id", new BasicDBObject("$gte", 10).append("$lte", 20));

BasicDBObject projection = new BasicDBObject();

projection.put("_id", 1);

long startTime = System.currentTimeMillis();

DBCursor cur = coll.find(predicate, projection );

DBObject foundObj;

while (cur.hasNext()) {

foundObj = cur.next();

}

long endTime = System.currentTimeMillis();

Solution: Limit the projection

Return fixed range

Page 34: Mythbusting: Understanding How We Measure Performance at MongoDB

BasicDBObject predicate = new BasicDBObject();

predicate.put("_id", new BasicDBObject("$gte", 10).append("$lte", 20));

BasicDBObject projection = new BasicDBObject();

projection.put("_id", 1);

long startTime = System.currentTimeMillis();

DBCursor cur = coll.find(predicate, projection );

DBObject foundObj;

while (cur.hasNext()) {

foundObj = cur.next();

}

long endTime = System.currentTimeMillis();

Solution: Limit the projection

Only project _id

Return fixed range

Page 35: Mythbusting: Understanding How We Measure Performance at MongoDB

BasicDBObject predicate = new BasicDBObject();

predicate.put("_id", new BasicDBObject("$gte", 10).append("$lte", 20));

BasicDBObject projection = new BasicDBObject();

projection.put("_id", 1);

long startTime = System.currentTimeMillis();

DBCursor cur = coll.find(predicate, projection );

DBObject foundObj;

while (cur.hasNext()) {

foundObj = cur.next();

}

long endTime = System.currentTimeMillis();

Solution: Limit the projection

Only project _id

Only 46k transferred through network stack

Return fixed range

Page 36: Mythbusting: Understanding How We Measure Performance at MongoDB

General Principal #2Measure only what you need to measure

Page 37: Mythbusting: Understanding How We Measure Performance at MongoDB

Part TwoPerformance measurement & diagnosis

Page 38: Mythbusting: Understanding How We Measure Performance at MongoDB

Broad categories

• Micro Benchmarks

• Workloads

Page 39: Mythbusting: Understanding How We Measure Performance at MongoDB

Micro benchmarks: mongo-perf

Page 40: Mythbusting: Understanding How We Measure Performance at MongoDB

mongo-perf: goals

• Measure– commands

• Configure– Single mongod, ReplSet size (1 -> n), Sharding– Single vs. Multiple DB– O/S

• Characterize– Throughput (ops/second) by thread count

• Compare

Page 41: Mythbusting: Understanding How We Measure Performance at MongoDB

What do you get?

Better

Thread Count

Ops/

Sec

Page 42: Mythbusting: Understanding How We Measure Performance at MongoDB

What do you get?

Measured improvement

between rc0 and rc2

Better

Page 43: Mythbusting: Understanding How We Measure Performance at MongoDB

tests.push( { name: "Commands.CountsIntIDRange", pre: function( collection ) { collection.drop(); for ( var i = 0; i < 1000; i++ ) { collection.insert( { _id : i } ); } collection.getDB().getLastError(); }, ops: [ { op: "command", ns : "testdb", command : { count : "mycollection", query : { _id : { "$gt" : 10, "$lt" : 100 } } } } ] } );

Benchmark source code

Page 44: Mythbusting: Understanding How We Measure Performance at MongoDB

tests.push( { name: "Commands.CountsIntIDRange", pre: function( collection ) { collection.drop(); for ( var i = 0; i < 1000; i++ ) { collection.insert( { _id : i } ); } collection.getDB().getLastError(); }, ops: [ { op: "command", ns : "testdb", command : { count : "mycollection", query : { _id : { "$gt" : 10, "$lt" : 100 } } } } ] } );

Benchmark source code

Page 45: Mythbusting: Understanding How We Measure Performance at MongoDB

tests.push( { name: "Commands.CountsIntIDRange", pre: function( collection ) { collection.drop(); for ( var i = 0; i < 1000; i++ ) { collection.insert( { _id : i } ); } collection.getDB().getLastError(); }, ops: [ { op: "command", ns : "testdb", command : { count : "mycollection", query : { _id : { "$gt" : 10, "$lt" : 100 } } } } ] } );

Benchmark source code

Page 46: Mythbusting: Understanding How We Measure Performance at MongoDB

tests.push( { name: "Commands.CountsIntIDRange", pre: function( collection ) { collection.drop(); for ( var i = 0; i < 1000; i++ ) { collection.insert( { _id : i } ); } collection.getDB().getLastError(); }, ops: [ { op: "command", ns : "testdb", command : { count : "mycollection", query : { _id : { "$gt" : 10, "$lt" : 100 } } } } ] } );

Benchmark source code

Page 47: Mythbusting: Understanding How We Measure Performance at MongoDB

Code Change

Page 48: Mythbusting: Understanding How We Measure Performance at MongoDB

Workloads

• "public" workloads– YCSB– Sysbench

• "real world" simulations– Inbox fan in/out– Message Stores– Content Management

Page 49: Mythbusting: Understanding How We Measure Performance at MongoDB

Example: Bulk Load Performance16m Documents

Better

55% degradation 2.6.0-rc1 vs

2.4.10

Page 50: Mythbusting: Understanding How We Measure Performance at MongoDB

Ouch… where's the tree in the woods?

• 2.4.10 -> 2.6.0– 4495 git commits

Page 51: Mythbusting: Understanding How We Measure Performance at MongoDB

git-bisect

• Bisect between good/bad hashes

• git-bisect nominates a new githash– Build against githash– Re-run test– Confirm if this githash is good/bad

• Rinse and repeat

Page 52: Mythbusting: Understanding How We Measure Performance at MongoDB

Code Change - Bad Githash

Page 53: Mythbusting: Understanding How We Measure Performance at MongoDB

Code Change - Fix

Page 54: Mythbusting: Understanding How We Measure Performance at MongoDB

Bulk Load Performance - Fix

Better

11% improvement

2.6.1 vs 2.4.10

Page 55: Mythbusting: Understanding How We Measure Performance at MongoDB

The problem with measurement

• Observability– What can you observe on the system?

• Effect– What effects does the observation cause?

Page 56: Mythbusting: Understanding How We Measure Performance at MongoDB

mtools

Page 57: Mythbusting: Understanding How We Measure Performance at MongoDB

mtools

• MongoDB log file analysis– Filter logs for operations, events– Response time, lock durations– Plot

• https://github.com/rueckstiess/mtools

Page 58: Mythbusting: Understanding How We Measure Performance at MongoDB

Code Change – Yielding Policy

Page 59: Mythbusting: Understanding How We Measure Performance at MongoDB

Code Change

Page 60: Mythbusting: Understanding How We Measure Performance at MongoDB

Response TimesBulk Insert 2.6.0 vs 2.6.1

Ceiling similar, lower floor resulting in 40% improvement in

throughput

Page 61: Mythbusting: Understanding How We Measure Performance at MongoDB

Secondary effects of Yield policy changeWrite lock time reduced

Order of magnitude reduction of write lock

duration

Page 62: Mythbusting: Understanding How We Measure Performance at MongoDB

> db.serverStatus()

Yes – will cause a read lock to be acquired

> db.serverStatus({recordStats:0})

No – lock is not acquired

> mongostat

Yes - until SERVER-14008 resolved, uses db.serverStatus()

Unexpected side effects of measurement?

Page 63: Mythbusting: Understanding How We Measure Performance at MongoDB

CPU sampling

• Get an impression of– Call Graphs– CPU time spent on node and called nodes

Page 64: Mythbusting: Understanding How We Measure Performance at MongoDB

> sudo apt-get install google-perftools

> sudo apt-get install libunwind7-dev

> scons --use-cpu-profiler mongod

Setup & building with google-profiler

Page 65: Mythbusting: Understanding How We Measure Performance at MongoDB

> mongod –dbpath <…>

Note: Do not use –fork

> mongo

> use admin

> db.runCommand({_cpuProfilerStart: {profileFilename: 'foo.prof'}})

Execute some commands that you want to profile

> db.runCommand({_cpuProfilerStop: 1})

Start the profiling

Page 66: Mythbusting: Understanding How We Measure Performance at MongoDB

Sample start vs. end of workload

Page 67: Mythbusting: Understanding How We Measure Performance at MongoDB

Sample start vs. end of workload

Page 68: Mythbusting: Understanding How We Measure Performance at MongoDB

Code change

Page 69: Mythbusting: Understanding How We Measure Performance at MongoDB

Public Benchmarks – Not all forks are the same…

• YCSB– https://github.com/achille/YCSB

• sysbench-mongodb– https://github.com/mdcallag/sysbench-mongodb

Page 70: Mythbusting: Understanding How We Measure Performance at MongoDB

[email protected]

VP, Engineering

Andrew Erlichson

#MongoDBDays

Thank You