diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d4f0cf392d36822bb238fc6cff1f290f3935ff2a..0ff78c22d2cc5a72ff40666e8d16d17ad3cd2c0b 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -117,7 +117,7 @@ clang-tidy:
 
 .emper-stats:
   variables:
-    EMPER_STATS: 'true'
+    EMPER_STATS_ALL: 'true'
 
 .emper-userspace-rcu:
   variables:
diff --git a/emper/Blockable.hpp b/emper/Blockable.hpp
index fa7019264be11def44de57ab3ed6087771c308ef..e5ba18c2664c8494a9a136b53b2028fa0f23a2d3 100644
--- a/emper/Blockable.hpp
+++ b/emper/Blockable.hpp
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: LGPL-3.0-or-later
-// Copyright © 2020-2021 Florian Schmaus
+// Copyright © 2020-2022 Florian Schmaus
 #pragma once
 
 #include <utility>
@@ -42,7 +42,7 @@ class Blockable : public Logger<logSubsystem> {
 				blockablePurpose(blockablePurpose) {}
 
 	void maybeSetAffinity() {
-		if constexpr (!emper::SET_AFFINITY_ON_BLOCK && !emper::STATS) return;
+		if constexpr (!emper::SET_AFFINITY_ON_BLOCK && !emper::STATS_BLOCKED_CONTEXT) return;
 
 		// TODO: At some point we may want to have something like
 		// Runtime::isAffinityCapable() and return here if it is
@@ -58,7 +58,7 @@ class Blockable : public Logger<logSubsystem> {
 			this->affinity = &affinity_buffer;
 		}
 
-		if (emper::STATS || setAffinityBuffer) {
+		if (emper::STATS_BLOCKED_CONTEXT || setAffinityBuffer) {
 			affinity_buffer = Runtime::getWorkerId();
 		}
 	}
@@ -75,23 +75,19 @@ class Blockable : public Logger<logSubsystem> {
 
 		maybeSetAffinity();
 
-		decltype(blockedContexts)::set_type::size_type blockedContextCount = 0;
+		if constexpr (emper::STATS_BLOCKED_CONTEXT_COUNT) {
+			size_t blockedContextCount =
+					runtime.blockedContextCount.fetch_add(1, std::memory_order_relaxed) + 1;
+			emper::stats::worker->recordBlockedContextCount(blockedContextCount);
+		}
+
 		if constexpr (emper::BLOCKED_CONTEXT_SET) {
 			auto* currentContext = Context::getCurrentContext();
-
-			if constexpr (emper::STATS) {
-				blockedContextCount = blockedContexts.insertAndGetSize(currentContext);
-			} else {
-				blockedContexts.insert(currentContext);
-			}
+			blockedContexts.insert(currentContext);
 		}
 
-		if constexpr (emper::STATS) {
-			// Note that blockedContextCount may not been set here if
-			// emper::BLOCKED_CONTEXT_SET is not enabled. But we will at
-			// least record a blocked context here if emper::STATS is
-			// enabled.
-			emper::stats::worker->recordBlockedContext(blockedContextCount, blockablePurpose);
+		if constexpr (emper::STATS_BLOCKED_CONTEXT) {
+			emper::stats::worker->recordBlockedContext(blockablePurpose);
 		}
 
 		contextManager.saveAndStartNew(std::move(freshContextHook));
@@ -99,11 +95,14 @@ class Blockable : public Logger<logSubsystem> {
 
 	auto unblockAndGetContinuation(Context* context) -> Fiber* {
 		assert(context != nullptr);
+		if constexpr (emper::STATS_BLOCKED_CONTEXT_COUNT) {
+			runtime.blockedContextCount.fetch_sub(1, std::memory_order_relaxed);
+		}
 		if constexpr (emper::BLOCKED_CONTEXT_SET) {
 			blockedContexts.erase(context);
 		}
 
-		if constexpr (emper::STATS) {
+		if constexpr (emper::STATS_BLOCKED_CONTEXT) {
 			if (likely(emper::stats::worker)) {
 				emper::stats::worker->recordUnblockedContext(affinity_buffer, blockablePurpose);
 			} else {
diff --git a/emper/Emper.hpp b/emper/Emper.hpp
index 02df6edf814c1231191add6857956f1ecfda8b95..77c40ed1c3b0c9eeb40161f29f1abc5e0733de1c 100644
--- a/emper/Emper.hpp
+++ b/emper/Emper.hpp
@@ -35,13 +35,18 @@ const StatsStackUsage STATS_STACK_USAGE = StatsStackUsage::EMPER_STATS_STACK_USA
 
 const bool STATS_STACK_USAGE_ENABLED = STATS_STACK_USAGE != StatsStackUsage::disabled;
 
+constexpr bool STATS_WORKER_SLEEP = EMPER_STATS_WORKER_SLEEP;
+constexpr bool STATS_BLOCKED_CONTEXT = EMPER_STATS_BLOCKED_CONTEXT;
+constexpr bool STATS_BLOCKED_CONTEXT_COUNT = EMPER_STATS_BLOCKED_CONTEXT_COUNT;
+
 const bool STATS =
 #ifdef EMPER_STATS
 		true
 #else
 		false
 #endif
-		|| STATS_STACK_USAGE_ENABLED;
+		|| STATS_STACK_USAGE_ENABLED || STATS_WORKER_SLEEP || STATS_BLOCKED_CONTEXT ||
+		STATS_BLOCKED_CONTEXT_COUNT;
 
 template <typename C>
 void statsIncr(C& counter) {
@@ -317,12 +322,4 @@ const bool STACK_GUARD_PAGE =
 #endif
 		;
 
-constexpr bool STATS_WORKER_SLEEP =
-#ifdef EMPER_STATS_WORKER_SLEEP
-		true
-#else
-		false
-#endif
-		;
-
 }	 // namespace emper
diff --git a/emper/Runtime.hpp b/emper/Runtime.hpp
index 9546b932d79e1d1efc001298c5a59fd479a598df..b8388f878b1d04137bcea6cb7749d1bdc419245e 100644
--- a/emper/Runtime.hpp
+++ b/emper/Runtime.hpp
@@ -121,6 +121,9 @@ class Runtime : public Logger<LogSubsystem::RUNTI> {
 	WorkerSleepStrategy workerSleepStrategy;
 	emper::WakeupStrategy wakeupStrategy;
 
+	// Per runtime-system stats
+	ALIGN_TO_CACHE_LINE std::atomic<size_t> blockedContextCount{0};
+
 	static StrategyFactory DEFAULT_STRATEGY_FACTORY;
 
 	static void printLastRuntimeStats(std::ostream& out = std::cout);
diff --git a/emper/stats/Worker.cpp b/emper/stats/Worker.cpp
index a984564ca09d8700100ac77830b99afee1ac90d0..3b2cac4e7d358f122927483db3447cc5516bba8c 100644
--- a/emper/stats/Worker.cpp
+++ b/emper/stats/Worker.cpp
@@ -20,9 +20,11 @@ Worker::Worker(workerid_t workerCount)
 			unblockAffinitiesIo(std::vector<uint32_t>(workerCount)),
 			lastStackUsage(32) {}
 
-void Worker::recordBlockedContext(size_t blockedContextCount, BlockablePurpose blockablePurpose) {
+void Worker::recordBlockedContextCount(size_t blockedContextCount) {
 	maxBlockedContexts = std::max(maxBlockedContexts, blockedContextCount);
+}
 
+void Worker::recordBlockedContext(BlockablePurpose blockablePurpose) {
 	switch (blockablePurpose) {
 		case BlockablePurpose::GENERIC:
 			blockedGeneric++;
@@ -66,14 +68,19 @@ void Worker::recordSleep(std::chrono::time_point<std::chrono::system_clock>& sle
 }
 
 auto Worker::operator+=(const Worker& other) -> Worker& {
-	maxBlockedContexts = std::max(maxBlockedContexts, other.maxBlockedContexts);
-	blockedGeneric += other.blockedGeneric;
-	blockedIo += other.blockedIo;
-
-	for (decltype(unblockAffinitiesGeneric)::size_type i = 0; i < unblockAffinitiesGeneric.size();
-			 i++) {
-		unblockAffinitiesGeneric[i] += other.unblockAffinitiesGeneric[i];
-		unblockAffinitiesIo[i] += other.unblockAffinitiesIo[i];
+	if constexpr (emper::STATS_BLOCKED_CONTEXT_COUNT) {
+		maxBlockedContexts = std::max(maxBlockedContexts, other.maxBlockedContexts);
+	}
+
+	if constexpr (emper::STATS_BLOCKED_CONTEXT) {
+		blockedGeneric += other.blockedGeneric;
+		blockedIo += other.blockedIo;
+
+		for (decltype(unblockAffinitiesGeneric)::size_type i = 0; i < unblockAffinitiesGeneric.size();
+				 i++) {
+			unblockAffinitiesGeneric[i] += other.unblockAffinitiesGeneric[i];
+			unblockAffinitiesIo[i] += other.unblockAffinitiesIo[i];
+		}
 	}
 
 	if constexpr (emper::STATS_STACK_USAGE_ENABLED) {
@@ -99,17 +106,22 @@ auto Worker::operator+=(const Worker& other) -> Worker& {
 }
 
 void Worker::print(std::ostream& out) {
-	out << "max-blocked-contexts: " << std::to_string(maxBlockedContexts) << std::endl
-			<< "blocked-generic: " << std::to_string(blockedGeneric) << std::endl;
-	for (decltype(unblockAffinitiesGeneric)::size_type i = 0; i < unblockAffinitiesGeneric.size();
-			 ++i) {
-		out << "unblock-affinities-generic" << std::to_string(i) << ": "
-				<< std::to_string(unblockAffinitiesGeneric[i]) << std::endl;
+	if constexpr (emper::STATS_BLOCKED_CONTEXT_COUNT) {
+		out << "max-blocked-contexts: " << std::to_string(maxBlockedContexts) << std::endl;
 	}
-	out << "blocked-io: " << std::to_string(blockedIo) << std::endl;
-	for (decltype(unblockAffinitiesIo)::size_type i = 0; i < unblockAffinitiesIo.size(); ++i) {
-		out << "unblock-affinities-io" << std::to_string(i) << ": "
-				<< std::to_string(unblockAffinitiesIo[i]) << std::endl;
+
+	if constexpr (emper::STATS_BLOCKED_CONTEXT) {
+		out << "blocked-generic: " << std::to_string(blockedGeneric) << std::endl;
+		for (decltype(unblockAffinitiesGeneric)::size_type i = 0; i < unblockAffinitiesGeneric.size();
+				 ++i) {
+			out << "unblock-affinities-generic" << std::to_string(i) << ": "
+					<< std::to_string(unblockAffinitiesGeneric[i]) << std::endl;
+		}
+		out << "blocked-io: " << std::to_string(blockedIo) << std::endl;
+		for (decltype(unblockAffinitiesIo)::size_type i = 0; i < unblockAffinitiesIo.size(); ++i) {
+			out << "unblock-affinities-io" << std::to_string(i) << ": "
+					<< std::to_string(unblockAffinitiesIo[i]) << std::endl;
+		}
 	}
 
 	if constexpr (emper::STATS_STACK_USAGE_ENABLED) {
diff --git a/emper/stats/Worker.hpp b/emper/stats/Worker.hpp
index c70dd52adf10ef9e0ef51f0af006c2f78c98fbd6..f302ddf9ef71d5606b29fdb4c758f4fa56312452 100644
--- a/emper/stats/Worker.hpp
+++ b/emper/stats/Worker.hpp
@@ -34,8 +34,8 @@ class Worker {
 
 	Worker(workerid_t workerCount);
 
-	void recordBlockedContext(size_t blockedContextCount, BlockablePurpose blockablePurpose);
-
+	void recordBlockedContextCount(size_t blockedContextCount);
+	void recordBlockedContext(BlockablePurpose blockablePurpose);
 	void recordUnblockedContext(workeraffinity_t workerAffinity, BlockablePurpose blockablePurpose);
 
 	size_t maxStackUsage = 0;
diff --git a/meson.build b/meson.build
index 9499fc8884237ddc99d50c45a36b4c60a9c4741e..d08933072666fc92f59feb13559ef2a59ef0a4f2 100644
--- a/meson.build
+++ b/meson.build
@@ -58,15 +58,12 @@ ws_queue_scheduler = get_option('ws_queue_scheduler')
 assume_page_size = get_option('assume_page_size')
 assume_cache_line_size = get_option('assume_cache_line_size')
 
-stats = get_option('stats')
-
 stats_all = get_option('stats_all')
 stats_worker_sleep_option = get_option('stats_worker_sleep')
-if stats_worker_sleep_option == 'enabled' or (stats_all and stats_worker_sleep_option == 'auto')
-  stats_worker_sleep = true
-  stats = true
+if stats_worker_sleep_option == 'true' or (stats_all and stats_worker_sleep_option == 'auto')
+  stats_worker_sleep = 'true'
 else
-  stats_worker_sleep = false
+  stats_worker_sleep = 'false'
 endif
 stats_stack_usage_option = get_option('stats_stack_usage')
 if stats_stack_usage_option == 'auto'
@@ -78,8 +75,17 @@ if stats_stack_usage_option == 'auto'
 else
   stats_stack_usage = stats_stack_usage_option
 endif
-if stats_stack_usage != 'disabled'
-  stats = true
+stats_blocked_context_option = get_option('stats_blocked_context')
+if stats_blocked_context_option == 'true' or (stats_all and stats_blocked_context_option == 'auto')
+  stats_blocked_context = 'true'
+else
+  stats_blocked_context = 'false'
+endif
+stats_blocked_context_count_option = get_option('stats_blocked_context_count')
+if stats_blocked_context_count_option == 'true' or (stats_all and stats_blocked_context_count_option == 'auto')
+  stats_blocked_context_count = 'true'
+else
+  stats_blocked_context_count = 'false'
 endif
 
 
@@ -88,7 +94,7 @@ conf_data.set('EMPER_WORKER_WAKEUP_STRATEGY', get_option('worker_wakeup_strategy
 conf_data.set('EMPER_WORKER_IGNORE_WAKEUP_HINT', get_option('worker_ignore_wakeup_hint'))
 conf_data.set('EMPER_LOCKED_MPSC_QUEUE', get_option('locked_mpsc_queue'))
 conf_data.set('EMPER_OVERFLOW_QUEUE', get_option('overflow_queue'))
-conf_data.set('EMPER_STATS', stats)
+conf_data.set('EMPER_STATS', get_option('stats'))
 conf_data.set('EMPER_OVERFLOW_QUEUE', get_option('overflow_queue'))
 conf_data.set('EMPER_BLOCKED_CONTEXT_SET', get_option('blocked_context_set'))
 conf_data.set('EMPER_SET_AFFINITY_ON_BLOCK', get_option('set_affinity_on_block'))
@@ -104,6 +110,8 @@ conf_data.set('EMPER_ASSUME_CACHE_LINE_SIZE', assume_cache_line_size)
 conf_data.set('EMPER_STACK_GUARD_PAGE', get_option('stack_guard_page'))
 conf_data.set('EMPER_STATS_STACK_USAGE', stats_stack_usage)
 conf_data.set('EMPER_STATS_WORKER_SLEEP', stats_worker_sleep)
+conf_data.set('EMPER_STATS_BLOCKED_CONTEXT', stats_blocked_context)
+conf_data.set('EMPER_STATS_BLOCKED_CONTEXT_COUNT', stats_blocked_context_count)
 
 context_alignment = get_option('context_alignment')
 if context_alignment == 'none'
diff --git a/meson_options.txt b/meson_options.txt
index 71da8976fe6eff571a2b6964da754f86c543b736..8762050f217ce4ae936c5cc54ceb6c92a4ec6517 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -138,13 +138,35 @@ option(
   'stats_worker_sleep',
   type: 'combo',
   choices: [
-    'disabled',
+    'false',
     'auto',
-    'enabled',
+    'true',
   ],
   value: 'auto',
   description: 'Collect stats about worker sleep',
 )
+option(
+  'stats_blocked_context',
+  type: 'combo',
+  choices: [
+    'false',
+    'auto',
+    'true',
+  ],
+  value: 'auto',
+  description: 'Collect stats about blocked contexts',
+)
+option(
+  'stats_blocked_context_count',
+  type: 'combo',
+  choices: [
+    'false',
+    'auto',
+    'true',
+  ],
+  value: 'auto',
+  description: 'Collect stats about number of blocked contexts',
+)
 option(
   'stats_all',
   type: 'boolean',