Skip to main content

Crate iona

Crate iona 

Source
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§

IonaBuffer
High performance, circular buffer.