Expand description
IonaBuffer is a high-performance, virtual memory-mirror implementation of a circular buffer,
which guarantees slices up to the capacity of the buffer are contiguous in memory. Wrapped reads
wrap to the same physical memory seamlessly.
use iona::IonaBuffer;
let mut buffer: IonaBuffer<usize> = match IonaBuffer::with_capacity(512) {
Ok(buffer) => buffer,
Err(_) => panic!("Unable to allocate the buffer"),
};
buffer.fill(0);
buffer.iter_mut().enumerate().for_each(|(i, value)| *value = i);
buffer.push_back(512); // this is now at the physical address 0
buffer.push_back(513); // this is now at the physical address 1
// No allocation/ concatenation needed when reading from the end of the physical buffer (the
// value `511`) to the next two values that were pushed to the back!
assert_eq!(buffer.get_from(509).to(3), Some(vec!(511,512,513).as_ref()));VIRTUAL ADDRESS SPACE
┌─────────────────────────────────┐
│ │
│ Page A [0x0000 - 0x0FFF] │──────────┐
│ │ │
├─────────────────────────────────┤ ▼
│ │ ┌──────────────────┐
│ Page B [0x1000 - 0x1FFF] │──►│ PHYSICAL MEMORY │
│ (mirror) │ │ │
└─────────────────────────────────┘ │ [ 0 ] data[0] │
│ [ 1 ] data[1] │
│ [ 2 ] data[2] │
write ptr │ ... │
│ │ [ N ] data[N] │◄── write ptr
▼ │ ... │
Page A: [ 0 | 1 | 2 | ... | N ] │ [ 0 ] data[0] │◄── read ptr
Page B: [ 0 | 1 | 2 | ... | N ] │ [ 1 ] data[1] │
▲ │ ... │
│ └──────────────────┘
read ptr
KEY BENEFIT: A contiguous read/write spanning the page boundary
never needs to wrap — the mirror handles it transparently.
read ptr write ptr
│ │
▼ ▼
Page A: [ 6 | 7 | 8 | 9 | 10 | 11 | 0 | 1 | 2 | 3 | 4 | 5 ]
╰──────────────────────────────────────╯
contiguous memcpy, no wrap logic!
Page B: [ 6 | 7 | 8 | 9 | 10 | 11 | 0 | 1 | 2 | 3 | 4 | 5 ]
^--- same physical bytes, just offset by one page§Trade-Offs
- Increased memory use: we double the used virtual memory space, but still only have a
single instance of physical memory backing the buffer. Moreover, this implementation
requires that the buffer is mapped to page size, which is typically 4KiB. So if
size_of::<T>()is small, the buffer will be relatively large and inefficient with memory use. The buffer also grows in size by powers of 2, so if 4KiB isn’t large enough, the next buffer size, on most machines, will be 8KiB.
Structs§
- Iona
Buffer - High performance, circular buffer.