Skip to content

Commit 8554f46

Browse files
authored
[runtime/iobuf/pool] don't cap tls cache at 8 buffers (#3685)
1 parent 9e86a82 commit 8554f46

1 file changed

Lines changed: 22 additions & 10 deletions

File tree

runtime/src/iobuf/pool.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,11 @@ const fn cache_line_size() -> usize {
127127
pub(crate) enum BufferPoolThreadCacheConfig {
128128
/// Enable thread-local caching.
129129
///
130-
/// `None` derives the per-thread cache size from the pool's expected
131-
/// parallelism. Small per-class budgets may resolve to zero, disabling
132-
/// thread-local caching so free buffers do not become stranded in other
133-
/// threads.
130+
/// `None` derives the per-thread cache size from the pool's per-class
131+
/// capacity and expected parallelism, reserving about half of each class
132+
/// for the shared freelist. Small per-class budgets may resolve to zero,
133+
/// disabling thread-local caching so free buffers do not become stranded in
134+
/// other threads.
134135
///
135136
/// `Some(n)` uses an exact per-thread cache size for every size class.
136137
Enabled(Option<NonZeroUsize>),
@@ -164,7 +165,9 @@ pub struct BufferPoolConfig {
164165
/// Expected number of threads concurrently accessing the pool.
165166
///
166167
/// This sizes the shared global freelist stripes. It is also used to derive
167-
/// thread-cache capacity when the thread-cache policy is automatic.
168+
/// thread-cache capacity when the thread-cache policy is automatic, using
169+
/// approximately half of [`Self::max_per_class`] divided across expected
170+
/// threads.
168171
pub parallelism: NonZeroUsize,
169172
/// Policy for sizing the per-thread local cache in each size class.
170173
///
@@ -241,7 +244,9 @@ impl BufferPoolConfig {
241244
/// Returns a copy of this config with a new expected parallelism.
242245
///
243246
/// This controls the minimum global-freelist stripe count, and controls
244-
/// thread-cache capacity when the thread-cache policy is automatic.
247+
/// thread-cache capacity when the thread-cache policy is automatic. The
248+
/// automatic policy reserves about half of each class for the global
249+
/// freelist and divides the remaining capacity across expected threads.
245250
pub const fn with_parallelism(mut self, parallelism: NonZeroUsize) -> Self {
246251
self.parallelism = parallelism;
247252
self
@@ -393,15 +398,15 @@ impl BufferPoolConfig {
393398

394399
/// Resolves the effective per-thread cache size for each size class.
395400
///
396-
/// Derived capacities reserve half of the class budget for the shared
397-
/// freelist so cross-thread reuse remains effective, and are capped at
398-
/// eight buffers per thread. Small class budgets may resolve to zero.
401+
/// Derived capacities divide half of the class budget across the expected
402+
/// parallelism so cross-thread reuse remains effective. Small class budgets
403+
/// may resolve to zero.
399404
fn resolve_thread_cache_capacity(&self) -> usize {
400405
match self.thread_cache_config {
401406
BufferPoolThreadCacheConfig::Enabled(None) => {
402407
let max_per_class = self.max_per_class.get() as usize;
403408
let effective_threads = self.parallelism.get().min(max_per_class);
404-
(max_per_class / (2 * effective_threads)).min(8)
409+
max_per_class / (2 * effective_threads)
405410
}
406411
BufferPoolThreadCacheConfig::Enabled(Some(thread_cache_capacity)) => {
407412
thread_cache_capacity.get()
@@ -1510,9 +1515,16 @@ mod tests {
15101515
#[test]
15111516
fn test_parallelism_policy_resolves_thread_cache_capacity() {
15121517
let page = page_size();
1518+
1519+
// Half the class budget is divided across expected threads.
15131520
let pool = test_pool(test_config(page, page, 64).with_parallelism(NZUsize!(8)));
15141521
let class_index = pool.inner.config.class_index(page).unwrap();
15151522
assert_eq!(pool.inner.classes[class_index].thread_cache_capacity, 4);
1523+
1524+
// Large classes scale past the previous eight-slot cap.
1525+
let pool = test_pool(test_config(page, page, 4096).with_parallelism(NZUsize!(8)));
1526+
let class_index = pool.inner.config.class_index(page).unwrap();
1527+
assert_eq!(pool.inner.classes[class_index].thread_cache_capacity, 256);
15161528
}
15171529

15181530
#[test]

0 commit comments

Comments
 (0)