]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore: Make OpSequencer has own deferred_lock. 30027/head
authorJianpeng Ma <jianpeng.ma@intel.com>
Wed, 16 Dec 2020 00:20:49 +0000 (08:20 +0800)
committerJianpeng Ma <jianpeng.ma@intel.com>
Wed, 16 Dec 2020 00:23:12 +0000 (08:23 +0800)
For 4k randwrite workload & Using perf script futex-contention in
60second, i found:
>bstore_mempool[69278] lock 7fdc0131f3b8 contended 5 times, 2043 avg ns
>bstore_kv_final[69277] lock 7fdc0131f3b8 contended 41835 times, 1285 avg ns
>bstore_aio[69226] lock 7fdc0131f3b8 contended 62294 times, 1217 avg ns

deferred_lock has serious contented. This becasue deferred_lock is a
globla lock. So i add defferred_lock in OpSequencer and make global
deferred_lock only protect deferred_queue.

After this change:
>bstore_kv_final[75810] lock 7f72f931f3b8 contended 1074 times, 1692 avg ns
>bstore_aio[75759] lock 7f72f931f3b8 contended 1491 times, 1133 avg ns

Signed-off-by: Jianpeng Ma <jianpeng.ma@intel.com>
src/common/Throttle.cc
src/os/bluestore/BlueStore.cc

index f25fa7cbe6edd1e78b3528aa1b2f563e82ef1ac9..b8b4783dce3050b800e1620468746995a88f1929 100644 (file)
@@ -191,25 +191,31 @@ bool Throttle::get_or_fail(int64_t c)
   }
 
   assert (c >= 0);
-  std::lock_guard l(lock);
-  if (_should_wait(c) || !conds.empty()) {
-    ldout(cct, 10) << "get_or_fail " << c << " failed" << dendl;
-    if (logger) {
-      logger->inc(l_throttle_get_or_fail_fail);
+  bool result = false;
+  {
+    std::lock_guard l(lock);
+    if (_should_wait(c) || !conds.empty()) {
+      ldout(cct, 10) << "get_or_fail " << c << " failed" << dendl;
+      result = false;
+    } else {
+      ldout(cct, 10) << "get_or_fail " << c << " success (" << count.load()
+       << " -> " << (count.load() + c) << ")" << dendl;
+      count += c;
+      result = true;
     }
-    return false;
-  } else {
-    ldout(cct, 10) << "get_or_fail " << c << " success (" << count.load()
-                  << " -> " << (count.load() + c) << ")" << dendl;
-    count += c;
-    if (logger) {
+  }
+
+  if (logger) {
+    if (result) {
       logger->inc(l_throttle_get_or_fail_success);
       logger->inc(l_throttle_get);
       logger->inc(l_throttle_get_sum, c);
       logger->set(l_throttle_val, count);
+    } else {
+      logger->inc(l_throttle_get_or_fail_fail);
     }
-    return true;
   }
+  return result;
 }
 
 int64_t Throttle::put(int64_t c)
@@ -222,19 +228,22 @@ int64_t Throttle::put(int64_t c)
   ceph_assert(c >= 0);
   ldout(cct, 10) << "put " << c << " (" << count.load() << " -> "
                 << (count.load()-c) << ")" << dendl;
-  std::lock_guard l(lock);
-  if (c) {
-    if (!conds.empty())
-      conds.front().notify_one();
-    // if count goes negative, we failed somewhere!
-    ceph_assert(count >= c);
-    count -= c;
-    if (logger) {
-      logger->inc(l_throttle_put);
-      logger->inc(l_throttle_put_sum, c);
-      logger->set(l_throttle_val, count);
+  {
+    std::lock_guard l(lock);
+    if (c) {
+      if (!conds.empty())
+       conds.front().notify_one();
+      // if count goes negative, we failed somewhere!
+      ceph_assert(count >= c);
+      count -= c;
     }
   }
+  if (logger) {
+    logger->inc(l_throttle_put);
+    logger->inc(l_throttle_put_sum, c);
+    logger->set(l_throttle_val, count);
+  }
+
   return count;
 }
 
index 468d846ff487e340805fc6742c20eb6048bb4b16..ae26d5943173324fdb0b3cde87115c464cdd73d2 100644 (file)
@@ -12159,6 +12159,8 @@ void BlueStore::_deferred_queue(TransContext *txc)
     txc->osr->deferred_lock.lock();
     ++deferred_queue_size;
     txc->osr->deferred_pending = tmp;
+    // condition "tmp->txcs.size() == 1" mean deferred_pending was originally empty.
+    // So we should add osr into deferred_queue.
     if (!txc->osr->deferred_running && (tmp->txcs.size() == 1)) {
       deferred_lock.lock();
       deferred_queue.push_back(*txc->osr);