Rust-rocksdb: Hacer que `cf_handle` no tenga bloqueos

Creado en 13 mar. 2019  ·  12Comentarios  ·  Fuente: rust-rocksdb/rust-rocksdb

La función cf_handle menudo se llama con mucha frecuencia y su implementación requiere adquirir un bloqueo de lectura en un mapa subyacente. Si se llama a esto en una ruta activa, puede tener implicaciones en el rendimiento. Deberíamos investigar cambiar esto a un enfoque que no requiera un bloqueo. Por ejemplo, podríamos hacer create_cf y drop_cf y cualquier otra función que mute el mapa interno requiera una referencia mutable a DB y hacer que la persona que llama sea responsable de adquirir los bloqueos en orden para mutar el DB .

Comentario más útil

Sí lo es. Planeamos lanzarlo en un futuro próximo.

Todos 12 comentarios

¿como esto?

use std::collections::HashMap;

#[derive(Debug)]
struct ColumnFamily(i32);

struct DB {
    cfs:HashMap<i32,ColumnFamily>,
}

impl DB {
    fn new()->DB{
        let mut cfs = HashMap::new();
        cfs.insert(1,ColumnFamily(1));
        cfs.insert(2,ColumnFamily(2));
        DB{
            cfs
        }
    }
    fn get(&self,key:i32)->&ColumnFamily{
        self.cfs.get(&key).unwrap()
    }
    fn drop_key(&mut self,key:i32){
        self.cfs.remove(&key);
    }
}

fn main() {
    let mut f = DB::new();
    let a = f.get(1);
    println!("{:?}",a);
    f.drop_key(1);
    let c = f.get(2);
    println!("{:?}",c);
}

FWIW, en la bifurcación de paritech cf_handle es Copy , que técnicamente no es seguro (OTOH uno diría que es difícil de usar incorrectamente), pero evita el uso de bloqueos.

@hjiayz Sí, muy similar a eso.

Cuando intenté hacer este cambio (es decir, tomar &mut self al crear / eliminar familias de columnas) encontré problemas con la forma en que se define ColumnFamily . Almacenará una referencia mutable en PhantomData que hace que un código como este falle:

#[test]
fn property_cf_test() {
    let n = DBPath::new("_rust_rocksdb_property_cf_test");
    {
        let opts = Options::default();
        let mut db = DB::open_default(&n).unwrap(); // Notice the `mut`
        let cf = db.create_cf("cf1", &opts).unwrap();
        let value = db.property_value_cf(cf, "rocksdb.stats").unwrap().unwrap();

        assert!(value.contains("Stats"));
    }
}

El error ocurre cuando se realiza una llamada a un método en db que toma &self , como db.property_value_cf() y pasa un ColumnFamily (que almacena un &mut en el db campo):

error[E0502]: cannot borrow `db` as immutable because it is also borrowed as mutable
  --> tests/test_property.rs:39:21
   |
38 |         let cf = db.create_cf("cf1", &opts).unwrap();
   |                  -- mutable borrow occurs here
39 |         let value = db.property_value_cf(cf, "rocksdb.stats").unwrap().unwrap();
   |                     ^^                   -- mutable borrow later used here
   |                     |
   |                     immutable borrow occurs here

No puedo pensar en una forma muy elegante de evitar esto, pero una opción es no devolver un ColumnFamily de create_cf y, en su lugar, dejar que el código de consumo lo busque con una llamada a cf_handle() :

#[test]
fn property_cf_test() {
    let n = DBPath::new("_rust_rocksdb_property_cf_test");
    {
        let opts = Options::default();
        let mut db = DB::open_default(&n).unwrap();
        db.create_cf("cf1", &opts).unwrap();
        let cf = db.cf_handle("cf1").unwrap(); // Get the CF
        let value = db.property_value_cf(cf, "rocksdb.stats").unwrap().unwrap();

        assert!(value.contains("Stats"));
    }
}

¿Cambiar create_cf() para devolver Result<(), Error> sería un cambio aceptable?

@dvdplm Agregar vidas ColumnFamily ha terminado siendo una pesadilla desde una perspectiva ergonómica. Me gustaría seguir un enfoque que no necesite toda la vida, pero que tampoco corra el riesgo de usar un puntero de familia de columnas después de que se haya eliminado. Es probable que ese cambio afecte la forma en que eliminamos los bloqueos de cf_handle ; probablemente no verá este problema.

De acuerdo con @iSynaptic. Obviamente, devolver una referencia a ColumnFamily es una forma segura solo en este caso.

¿Quizás el # 298 pueda fusionarse entonces?

314

¿Está resuelto por el # 314? ¿Algún plan de lanzamiento si es así?

Sí lo es. Planeamos lanzarlo en un futuro próximo.

@aleksuss ¿cuál es el estado de su lanzamiento? :)

@bkchr Creo que lo haremos la semana que viene.

¿Fue útil esta página
0 / 5 - 0 calificaciones