Memory mapping.
Una de las cosas a mirar cuando elegimos una DB que la gente no entiende, es como la vamos a usar? No todas las DB van a ir igual de bien en cuanto a rendimiento.
En este caso, estamos haciendo una KV, pero no hemos definido el caso de uso que queremos resolver exactamente, como se va a usar nuestra base de datos. Esto ES CRITICO y LO MAS IMPORTANTE.
Veamos el problema:
fn get(key) -> Vec<u8> {
return new copy of a vector of bytes!
}
El problema es que cada vez que hacemos un get, vamos a devolver una copia de lo que leamos de disco. Es esto lo que queremos? Yo puedo usar buffers y pools para tener zero copy y re usar los buffer entre lecturas de disco a mi base de datos. Pero como decido como devolverte los datos? Depende de que va a hacer con ellos no? Los quieres consultar? Los quieres pasar por network? Los quieres modificar y re-escribir? Los vas a usar desde el mismo proceso? En otro thread quizas? Esto es LO MAS IMPORTANTE.
Veamos como lo hacen otras bases de datos:
- mmap para compartir memoria: rockdb
- seguramente lo mas rapido, porque podemos literar mappear la region de nuestro log a memoria y compartirlo al toque
- borrow referencia del pool: lmdb
- nuestro proceso es el owner de la memoria, no se puede modificar
- zero copy con ARC: sqlite
- parecido al punto anterior, pero usando un ARC sobre el slice de memoria que compartimos para saber cuando droppear
En codigo gracias a Claude:
- Memory-mapped (best for random access, shared memory):
// Zero-copy, but whole file in virtual memory
pub fn get(&self) -> Result<&[u8], Error> {
let mmap = &self.mmaps[file_id];
Ok(&mmap[offset..offset+len])
}
- Buffered reads (best for streaming/sequential):
pub fn get<'a>(&'a mut self) -> Result<ValueRef<'a>, Error> {
let buf = self.pool.pull();
reader.read_exact(buf)?;
Ok(ValueRef { data: buf })
}
- Reference counted (best for concurrent/async):
// Flexible but has overhead
pub fn get(&self) -> Result<Arc<[u8]>, Error> {
let data = Arc::new(read_data()?);
Ok(data)
}
El ejercicio ahora es simple, tu fpero, sabes como devuelve memoria tu DB? Porque es una de las decisiones principales al elegir una base de datos.
Y que haces con estos datos? Los pasas a disco de nuevo modificados, o por network, o simplemente los consultas en memoria y después los descartas?