summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2014-12-09 15:37:09 -0500
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2014-12-09 20:22:58 -0500
commit5b44e4b489ef6a8eca4e48d3124665f404cc2c92 (patch)
treeaf2c6ada1948aa2c0f1a2de6ccab527f8c666912 /src/mongo/db
parent604fc8c629b4cd90a3fbd84e53eb4c892878a318 (diff)
downloadmongo-5b44e4b489ef6a8eca4e48d3124665f404cc2c92.tar.gz
SERVER-16482 Do not look further in the conflict queue if X lock was just granted
This is a small optimization, which would help with the LM cost in the presence of X-lock conflicts, such as the MMAP V1 collection lock.
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/concurrency/lock_mgr_new.cpp22
1 files changed, 20 insertions, 2 deletions
diff --git a/src/mongo/db/concurrency/lock_mgr_new.cpp b/src/mongo/db/concurrency/lock_mgr_new.cpp
index ac64ce1fc6b..887461167ef 100644
--- a/src/mongo/db/concurrency/lock_mgr_new.cpp
+++ b/src/mongo/db/concurrency/lock_mgr_new.cpp
@@ -732,7 +732,17 @@ namespace {
}
}
- // Grant any conflicting requests, which might now be unblocked
+ // Grant any conflicting requests, which might now be unblocked. Note that the loop below
+ // slightly violates fairness in that it will grant *all* compatible requests on the line
+ // even though there might be conflicting ones interspersed between them. For example,
+ // consider an X lock was just freed and the conflict queue looked like this:
+ //
+ // IS -> IS -> X -> X -> S -> IS
+ //
+ // In strict FIFO, we should grant the first two IS modes and then stop when we reach the
+ // first X mode (the third request on the queue). However, the loop below would actually
+ // grant all IS + S modes and once they all drain it will grant X.
+
LockRequest* iterNext = NULL;
for (LockRequest* iter = lock->conflictList._front;
@@ -745,7 +755,9 @@ namespace {
// the granted queue.
iterNext = iter->next;
- if (conflicts(iter->mode, lock->grantedModes)) continue;
+ if (conflicts(iter->mode, lock->grantedModes)) {
+ continue;
+ }
iter->status = LockRequest::STATUS_GRANTED;
@@ -760,6 +772,12 @@ namespace {
}
iter->notify->notify(lock->resourceId, LOCK_OK);
+
+ // Small optimization - nothing is compatible with MODE_X, so no point in looking
+ // further in the conflict queue.
+ if (iter->mode == MODE_X) {
+ break;
+ }
}
// This is a convenient place to check that the state of the two request queues is in sync