]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
test/common: reduce WebCache stress-test thread count
authorKefu Chai <k.chai@proxmox.com>
Mon, 22 Jun 2026 12:48:41 +0000 (20:48 +0800)
committerKefu Chai <k.chai@proxmox.com>
Thu, 2 Jul 2026 01:46:12 +0000 (09:46 +0800)
WebCacheConcurrencyTest sized its thread pool as hardware_concurrency() * 100,
which is 3200 on the 32-vCPU CI hosts. Linux runs that in a few seconds, but
the Windows (mingw-llvm/libc++) build times out unittest_web_cache at the
1800s per-test limit on every PR.

BasicAddSame reuses one key, so after the first insert every add() is a
shared-lock hit: 3200 threads log hit=3200000 miss=1 and finish in ~4s.
BasicAddUnique inserts a distinct key each iteration, so every add() misses
and takes the exclusive lock. libc++'s std::shared_mutex wakes all waiting
writers on every unlock, so N contending writers cost O(N^2) wakeups. At
N=3200 that alone overruns the 1800s budget, which is where the failing run
hangs. StampedeSyncCallOnce and StampedeMutex are exclusive-lock bound the
same way.

The tests only need enough threads to race; 4x oversubscription is enough.
Cap the count via a shared helper.

Signed-off-by: Kefu Chai <k.chai@proxmox.com>
src/test/common/test_web_cache.cc

index 524e4c0beb2b5a6f8a49141025442b23f948a6f8..6bbcbdc4a153f05985ae2fb13a526fb24e2d5354 100644 (file)
@@ -446,6 +446,13 @@ TEST_F(WebCacheTest, SieveAllVisited) {
 }
 
 class WebCacheConcurrencyTest : public WebCacheTest {
+ protected:
+  // 4x oversubscription is enough to race the threads. The original *100
+  // (3200 on CI) made exclusive-lock tests O(N^2) and timed out on Windows.
+  static unsigned stress_thread_count() {
+    return std::max(std::thread::hardware_concurrency() * 4, 32u);
+  }
+
   void TearDown() override {
     if (_uut->perf() != nullptr) {
       JSONFormatter f(true);
@@ -458,8 +465,7 @@ class WebCacheConcurrencyTest : public WebCacheTest {
 
 TEST_F(WebCacheConcurrencyTest, BasicAddSame) {
   reset_cache_system_mode(100);
-  const auto num_threads =
-      std::max(std::thread::hardware_concurrency() * 100, 100U);
+  const auto num_threads = stress_thread_count();
   std::vector<std::thread> threads;
   for (size_t i = 0; i < num_threads; ++i) {
     threads.emplace_back([&]() {
@@ -478,8 +484,7 @@ TEST_F(WebCacheConcurrencyTest, BasicAddSame) {
 
 TEST_F(WebCacheConcurrencyTest, BasicAddUnique) {
   reset_cache_system_mode(100);
-  const auto num_threads =
-      std::max(std::thread::hardware_concurrency() * 100, 100U);
+  const auto num_threads = stress_thread_count();
   std::vector<std::thread> threads;
   for (size_t i = 0; i < num_threads; ++i) {
     threads.emplace_back([&]() {
@@ -504,8 +509,7 @@ TEST_F(WebCacheConcurrencyTest, StampedeSyncCallOnce) {
   webcache::WebCache<std::string, CacheValue> cache(
       _cct.get(), "test_web_cache", 100);
   std::atomic_int fetches = 0;
-  const auto num_threads =
-      std::max(std::thread::hardware_concurrency() * 100, 100U);
+  const auto num_threads = stress_thread_count();
   std::vector<std::thread> threads;
   for (size_t i = 0; i < num_threads; ++i) {
     threads.emplace_back([&]() {
@@ -542,8 +546,7 @@ TEST_F(WebCacheConcurrencyTest, StampedeMutex) {
   webcache::WebCache<std::string, CacheValue> cache(
       _cct.get(), "test_web_cache", 100);
   std::atomic_int fetches = 0;
-  const auto num_threads =
-      std::max(std::thread::hardware_concurrency() * 100, 100U);
+  const auto num_threads = stress_thread_count();
   std::vector<std::thread> threads;
   for (size_t i = 0; i < num_threads; ++i) {
     threads.emplace_back([&]() {