Open a Vamana index file for io_uring-backed vector fetching. `pool_size` is the number of pre-allocated aligned read buffers. A good default is `2 * beam_width` (e.g. 128 for `l_search = 64`).
(
path: &std::path::Path,
layout: VamanaStorageLayout,
pool_size: usize,
)
| 62 | /// `pool_size` is the number of pre-allocated aligned read buffers. |
| 63 | /// A good default is `2 * beam_width` (e.g. 128 for `l_search = 64`). |
| 64 | pub fn open( |
| 65 | path: &std::path::Path, |
| 66 | layout: VamanaStorageLayout, |
| 67 | pool_size: usize, |
| 68 | ) -> std::io::Result<Self> { |
| 69 | let file = std::fs::OpenOptions::new().read(true).open(path)?; |
| 70 | let ring = io_uring::IoUring::new(VAMANA_QUEUE_DEPTH).map_err(std::io::Error::other)?; |
| 71 | |
| 72 | let vector_bytes = layout.dim as usize * 4; // f32 = 4 bytes |
| 73 | let buf_size = align_up(vector_bytes, ALIGNMENT); |
| 74 | |
| 75 | let mut buf_pool = Vec::with_capacity(pool_size); |
| 76 | let mut free_bufs = Vec::with_capacity(pool_size); |
| 77 | for i in 0..pool_size { |
| 78 | match AlignedBuf::new(buf_size) { |
| 79 | Ok(buf) => { |
| 80 | buf_pool.push(buf); |
| 81 | free_bufs.push(i); |
| 82 | } |
| 83 | Err(_) => break, |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | if buf_pool.is_empty() { |
| 88 | return Err(std::io::Error::new( |
| 89 | std::io::ErrorKind::OutOfMemory, |
| 90 | "IoUringNodeFetcher: failed to allocate buffer pool", |
| 91 | )); |
| 92 | } |
| 93 | |
| 94 | Ok(Self { |
| 95 | ring, |
| 96 | file, |
| 97 | layout, |
| 98 | completed: HashMap::new(), |
| 99 | in_flight: 0, |
| 100 | buf_pool, |
| 101 | free_bufs, |
| 102 | pending: HashMap::new(), |
| 103 | }) |
| 104 | } |
| 105 | |
| 106 | /// Drain all pending completions into `self.completed`. |
| 107 | /// |