-
-
Notifications
You must be signed in to change notification settings - Fork 563
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(rust): added global buffer allocator to reduce memory fragmentation
- Loading branch information
1 parent
05fbf4b
commit d432379
Showing
17 changed files
with
205 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
implementations/rust/ockam/ockam_core/src/buffer_pool.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
#[cfg(feature = "std")] | ||
use once_cell::sync::Lazy; | ||
|
||
#[cfg(feature = "std")] | ||
/// The global instance of [`BufferPool`]. | ||
/// The goal of this pool is to reduce memory fragmentation by keep reusing the same buffers. | ||
pub static GLOBAL_BUFFER_POOL: Lazy<std::BufferPool> = Lazy::new(std::BufferPool::new); | ||
|
||
#[cfg(not(feature = "std"))] | ||
/// The global instance of [`BufferPool`]. | ||
/// The goal of this pool is to reduce memory fragmentation by keep reusing the same buffers. | ||
pub static GLOBAL_BUFFER_POOL: no_std::BufferPool = no_std::BufferPool {}; | ||
|
||
#[cfg(feature = "std")] | ||
mod std { | ||
use crate::compat::sync::Mutex; | ||
use crate::compat::vec::Vec; | ||
|
||
const MIN_BUFFER_SIZE: usize = 96 * 1024; | ||
const MAX_BUFFER_SIZE: usize = 192 * 1024; | ||
const MAX_BUFFERS: usize = 32; | ||
|
||
/// A buffer pool for reusing buffers at least big as [`MIN_BUFFER_SIZE`]. | ||
pub struct BufferPool { | ||
buffers: Mutex<Inner>, | ||
} | ||
|
||
struct Inner { | ||
buffers: Vec<Vec<u8>>, | ||
} | ||
|
||
impl BufferPool { | ||
pub(super) fn new() -> Self { | ||
// pre-allocate a big buffer to help reduce memory fragmentation | ||
_ = Vec::<u8>::with_capacity(1024 * 1024 * 32); | ||
Self { | ||
buffers: Mutex::new(Inner { | ||
buffers: Vec::new(), | ||
}), | ||
} | ||
} | ||
|
||
/// When the size is big enough, it'll return a buffer from the pool, | ||
/// otherwise it'll return a new buffer. | ||
pub fn try_size(&self, size: usize) -> Vec<u8> { | ||
if (MIN_BUFFER_SIZE..=MAX_BUFFER_SIZE).contains(&size) { | ||
self.take() | ||
} else { | ||
Vec::with_capacity(size) | ||
} | ||
} | ||
|
||
/// Take a buffer from the pool. | ||
pub fn take(&self) -> Vec<u8> { | ||
let mut buffers = self.buffers.lock().unwrap(); | ||
if let Some(mut buffer) = buffers.buffers.pop() { | ||
buffer.clear(); | ||
buffer | ||
} else { | ||
Vec::with_capacity(MIN_BUFFER_SIZE) | ||
} | ||
} | ||
|
||
/// Release a buffer back to the pool, the buffer will only be reused if | ||
/// it's capacity is within [`MIN_BUFFER_SIZE`] and [`MAX_BUFFER_SIZE`]. | ||
pub fn release(&self, buffer: Vec<u8>) { | ||
if buffer.capacity() >= MIN_BUFFER_SIZE && buffer.capacity() <= MAX_BUFFER_SIZE { | ||
let mut buffers = self.buffers.lock().unwrap(); | ||
if buffers.buffers.len() < MAX_BUFFERS { | ||
buffers.buffers.push(buffer); | ||
// we can assume the smaller allocations are the newer ones, | ||
// by returning the smaller ones first, we should be able | ||
// to avoid "refreshing" the buffer pool too often | ||
buffers.buffers.sort_by_key(|b| -(b.capacity() as i64)); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[cfg(not(feature = "std"))] | ||
mod no_std { | ||
use crate::compat::vec::Vec; | ||
|
||
/// A buffer pool for reusing buffers at least big as [`MIN_BUFFER_SIZE`]. | ||
pub struct BufferPool; | ||
|
||
impl BufferPool { | ||
/// When the size is big enough, it'll return a buffer from the pool, | ||
/// otherwise it'll return a new buffer. | ||
pub fn try_size(&self, size: usize) -> Vec<u8> { | ||
Vec::with_capacity(size) | ||
} | ||
|
||
/// Take a buffer from the pool. | ||
pub fn take(&self) -> Vec<u8> { | ||
Vec::new() | ||
} | ||
|
||
/// Release a buffer back to the pool, the buffer will only be reused if | ||
/// it's capacity is within [`MIN_BUFFER_SIZE`] and [`MAX_BUFFER_SIZE`]. | ||
pub fn release(&self, _buffer: Vec<u8>) {} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.