This is an automated email from the ASF dual-hosted git repository.

zwoop pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 2bbc66f984 Parallelize dir-sync on graceful shutdowns (#12996)
2bbc66f984 is described below

commit 2bbc66f984d5bb498467456667ea8463fb325039
Author: Leif Hedstrom <[email protected]>
AuthorDate: Wed May 6 09:10:36 2026 -0600

    Parallelize dir-sync on graceful shutdowns (#12996)
    
    * Parallelize dir-sync on graceful shutdowns
    
    This will make normal ATS shutdowns come down quicker, specially on
    boxes with a lot of drives. This is similar to the new parallel sync
    options under normal operations, except this will always Parallelize
    as much as needed.
    
    * Address Copilot's review comments
    
    Fix lambda reference capture bug where all threads processed the last disk's
    stripes instead of their own; fix shared 0xdeadbeef EThread* sentinel by 
using
    a thread_local variable to give each OS thread a unique identity for
    MUTEX_TAKE_LOCK.
---
 src/iocore/cache/CacheDir.cc | 38 ++++++++++++++++++++++++++++++++------
 1 file changed, 32 insertions(+), 6 deletions(-)

diff --git a/src/iocore/cache/CacheDir.cc b/src/iocore/cache/CacheDir.cc
index 1e1c79df07..ee14d521ff 100644
--- a/src/iocore/cache/CacheDir.cc
+++ b/src/iocore/cache/CacheDir.cc
@@ -33,6 +33,7 @@
 #include "ts/ats_probe.h"
 #include "iocore/eventsystem/Tasks.h"
 
+#include <thread>
 #include <unordered_map>
 
 #ifdef LOOP_CHECK_MODE
@@ -957,20 +958,45 @@ Directory::entries_used()
 }
 
 /*
- * this function flushes the cache meta data to disk when
+ * This function flushes the cache meta data to disk when
  * the cache is shutdown. Must *NOT* be used during regular
- * operation.
+ * operation. Stripes are synced in parallel, one thread per
+ * physical disk.
  */
 
 void
 sync_cache_dir_on_shutdown()
 {
-  Dbg(dbg_ctl_cache_dir_sync, "sync started");
-  EThread *t = reinterpret_cast<EThread *>(0xdeadbeef);
+  Dbg(dbg_ctl_cache_dir_sync, "shutdown sync started");
+
+  std::unordered_map<CacheDisk *, std::vector<int>> drive_stripe_map;
+
   for (int i = 0; i < gnstripes; i++) {
-    gstripes[i]->shutdown(t);
+    drive_stripe_map[gstripes[i]->disk].push_back(i);
+  }
+
+  std::vector<std::thread> threads;
+
+  threads.reserve(drive_stripe_map.size());
+  for (auto &[disk, indices] : drive_stripe_map) {
+    Dbg(dbg_ctl_cache_dir_sync, "Disk %s: syncing %zu stripe(s)", disk->path, 
indices.size());
+    auto stripe_indices = indices;
+    threads.emplace_back([stripe_indices]() {
+      // Use a thread_local variable to give each OS thread a unique EThread* 
sentinel instead of 0xdeadbeef.
+      thread_local char thread_sentinel;
+      EThread          *t = reinterpret_cast<EThread *>(&thread_sentinel);
+
+      for (int idx : stripe_indices) {
+        gstripes[idx]->shutdown(t);
+      }
+    });
   }
-  Dbg(dbg_ctl_cache_dir_sync, "sync done");
+
+  for (auto &thr : threads) {
+    thr.join();
+  }
+
+  Dbg(dbg_ctl_cache_dir_sync, "shutdown sync done");
 }
 
 int

Reply via email to