4949//! first try to re-enter the dropping thread's local cache, spilling a bounded
5050//! batch back to the global freelist if needed.
5151
52- use super :: { freelist:: Freelist , IoBufMut } ;
52+ use super :: { freelist:: Freelist , page_size , IoBufMut } ;
5353use crate :: {
5454 iobuf:: buffer:: { PooledBufMut , PooledBuffer } ,
5555 telemetry:: metrics:: { raw, Counter , CounterFamily , EncodeLabelSet , GaugeFamily , Register } ,
5656} ;
5757use commonware_utils:: { NZUsize , NZU32 } ;
58- use crossbeam_utils:: CachePadded ;
5958use std:: {
6059 alloc:: Layout ,
6160 cell:: { Cell , UnsafeCell } ,
62- mem:: { align_of , MaybeUninit } ,
61+ mem:: MaybeUninit ,
6362 num:: { NonZeroU32 , NonZeroUsize } ,
6463 ptr,
6564 sync:: {
@@ -95,35 +94,6 @@ impl std::fmt::Display for PoolError {
9594
9695impl std:: error:: Error for PoolError { }
9796
98- /// Returns the system page size.
99- ///
100- /// On Unix systems, queries the actual page size via `sysconf`.
101- /// On other systems (Windows), defaults to 4KB.
102- #[ cfg( unix) ]
103- fn page_size ( ) -> usize {
104- // SAFETY: sysconf is safe to call.
105- let size = unsafe { libc:: sysconf ( libc:: _SC_PAGESIZE) } ;
106- if size <= 0 {
107- 4096 // Safe fallback if sysconf fails
108- } else {
109- size as usize
110- }
111- }
112-
113- #[ cfg( not( unix) ) ]
114- #[ allow( clippy:: missing_const_for_fn) ]
115- fn page_size ( ) -> usize {
116- 4096
117- }
118-
119- /// Returns the cache line size for the current architecture.
120- ///
121- /// Matches the architecture-specific alignment used by
122- /// [`crossbeam_utils::CachePadded`].
123- const fn cache_line_size ( ) -> usize {
124- align_of :: < CachePadded < u8 > > ( )
125- }
126-
12797/// Policy for sizing each thread's cache within a buffer pool size class.
12898#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
12999pub ( crate ) enum BufferPoolThreadCacheConfig {
@@ -184,40 +154,36 @@ pub struct BufferPoolConfig {
184154}
185155
186156impl BufferPoolConfig {
187- /// Network I/O preset: cache-line aligned, 1KB to 64KB buffers,
188- /// 4096 per class, not prefilled.
157+ /// Network I/O preset: 1KB to 128KB buffers, 4096 per class, not prefilled.
189158 ///
190- /// Network operations typically need multiple concurrent buffers per connection
191- /// (message, encoding, encryption) so we allow 4096 buffers per size class.
192- /// Cache-line alignment is used because network buffers don't require page
193- /// alignment for DMA, and smaller alignment reduces internal fragmentation.
159+ /// Network operations typically need multiple concurrent buffers per
160+ /// connection (message, encoding, encryption) so we allow 4096 buffers per
161+ /// size class.
194162 pub const fn for_network ( ) -> Self {
195- let cache_line = NZUsize ! ( cache_line_size( ) ) ;
196163 Self {
197- pool_min_size : 1024 ,
164+ pool_min_size : 0 ,
198165 min_size : NZUsize ! ( 1024 ) ,
199- max_size : NZUsize ! ( 64 * 1024 ) ,
166+ max_size : NZUsize ! ( 128 * 1024 ) ,
200167 max_per_class : NZU32 ! ( 4096 ) ,
201168 prefill : false ,
202- alignment : cache_line ,
169+ alignment : NZUsize ! ( 1 ) ,
203170 parallelism : NZUsize ! ( 1 ) ,
204171 thread_cache_config : BufferPoolThreadCacheConfig :: Enabled ( None ) ,
205172 }
206173 }
207174
208- /// Storage I/O preset: page-aligned, page_size to 8MB buffers, 64 per class,
175+ /// Storage I/O preset: ` page_size` (usually 4KB) to 8MB buffers, 64 per class,
209176 /// not prefilled.
210- ///
211- /// Page alignment is required for direct I/O and efficient DMA transfers.
212177 pub fn for_storage ( ) -> Self {
213178 let page = NZUsize ! ( page_size( ) ) ;
214179 Self {
215- pool_min_size : 1024 ,
180+ pool_min_size : 0 ,
216181 min_size : page,
217182 max_size : NZUsize ! ( 8 * 1024 * 1024 ) ,
218183 max_per_class : NZU32 ! ( 64 ) ,
219184 prefill : false ,
220- alignment : page,
185+ // TODO (#2960): this needs to be page/block aligned for O_DIRECT
186+ alignment : NZUsize ! ( 1 ) ,
221187 parallelism : NZUsize ! ( 1 ) ,
222188 thread_cache_config : BufferPoolThreadCacheConfig :: Enabled ( None ) ,
223189 }
@@ -1745,7 +1711,7 @@ impl BufferPool {
17451711mod tests {
17461712 use super :: * ;
17471713 use crate :: {
1748- iobuf:: { freelist, IoBuf } ,
1714+ iobuf:: { cache_line_size , freelist, IoBuf } ,
17491715 telemetry:: metrics:: Registry ,
17501716 } ;
17511717 use bytes:: { Buf , BufMut } ;
@@ -2053,24 +2019,24 @@ mod tests {
20532019 fn test_config_for_network ( ) {
20542020 let config = BufferPoolConfig :: for_network ( ) ;
20552021 config. validate ( ) ;
2056- assert_eq ! ( config. pool_min_size, 1024 ) ;
2022+ assert_eq ! ( config. pool_min_size, 0 ) ;
20572023 assert_eq ! ( config. min_size. get( ) , 1024 ) ;
2058- assert_eq ! ( config. max_size. get( ) , 64 * 1024 ) ;
2024+ assert_eq ! ( config. max_size. get( ) , 128 * 1024 ) ;
20592025 assert_eq ! ( config. max_per_class. get( ) , 4096 ) ;
20602026 assert_eq ! ( config. parallelism, NZUsize !( 1 ) ) ;
20612027 assert_eq ! (
20622028 config. thread_cache_config,
20632029 BufferPoolThreadCacheConfig :: Enabled ( None )
20642030 ) ;
20652031 assert ! ( !config. prefill) ;
2066- assert_eq ! ( config. alignment. get( ) , cache_line_size ( ) ) ;
2032+ assert_eq ! ( config. alignment. get( ) , 1 ) ;
20672033 }
20682034
20692035 #[ test]
20702036 fn test_config_for_storage ( ) {
20712037 let config = BufferPoolConfig :: for_storage ( ) ;
20722038 config. validate ( ) ;
2073- assert_eq ! ( config. pool_min_size, 1024 ) ;
2039+ assert_eq ! ( config. pool_min_size, 0 ) ;
20742040 assert_eq ! ( config. min_size. get( ) , page_size( ) ) ;
20752041 assert_eq ! ( config. max_size. get( ) , 8 * 1024 * 1024 ) ;
20762042 assert_eq ! ( config. max_per_class. get( ) , 64 ) ;
@@ -2080,7 +2046,7 @@ mod tests {
20802046 BufferPoolThreadCacheConfig :: Enabled ( None )
20812047 ) ;
20822048 assert ! ( !config. prefill) ;
2083- assert_eq ! ( config. alignment. get( ) , page_size ( ) ) ;
2049+ assert_eq ! ( config. alignment. get( ) , 1 ) ;
20842050 }
20852051
20862052 #[ test]
@@ -2115,8 +2081,7 @@ mod tests {
21152081 BufferPoolThreadCacheConfig :: Enabled ( Some ( NZUsize !( 8 ) ) )
21162082 ) ;
21172083 assert ! ( config. prefill) ;
2118- // Storage profile alignment stays page-sized unless explicitly changed.
2119- assert_eq ! ( config. alignment. get( ) , page_size( ) ) ;
2084+ assert_eq ! ( config. alignment. get( ) , 1 ) ;
21202085
21212086 // Alignment can be tuned explicitly as long as min_size is also adjusted.
21222087 let aligned = BufferPoolConfig :: for_network ( )
@@ -3142,20 +3107,23 @@ mod tests {
31423107 fn test_buffer_alignment ( ) {
31433108 let page = page_size ( ) ;
31443109 let cache_line = cache_line_size ( ) ;
3110+
31453111 // Reduce max_per_class under miri (atomics are slow)
31463112 cfg_if:: cfg_if! {
31473113 if #[ cfg( miri) ] {
31483114 let storage_config = BufferPoolConfig {
31493115 max_per_class: NZU32 !( 32 ) ,
3150- ..BufferPoolConfig :: for_storage( )
3116+ ..BufferPoolConfig :: for_storage( ) . with_alignment ( NZUsize ! ( page ) )
31513117 } ;
31523118 let network_config = BufferPoolConfig {
31533119 max_per_class: NZU32 !( 32 ) ,
3154- ..BufferPoolConfig :: for_network( )
3120+ ..BufferPoolConfig :: for_network( ) . with_alignment ( NZUsize ! ( cache_line ) )
31553121 } ;
31563122 } else {
3157- let storage_config = BufferPoolConfig :: for_storage( ) ;
3158- let network_config = BufferPoolConfig :: for_network( ) ;
3123+ let storage_config =
3124+ BufferPoolConfig :: for_storage( ) . with_alignment( NZUsize !( page) ) ;
3125+ let network_config =
3126+ BufferPoolConfig :: for_network( ) . with_alignment( NZUsize !( cache_line) ) ;
31593127 }
31603128 }
31613129
0 commit comments