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