Rust-rocksdb: Rendre `cf_handle` sans verrou

Créé le 13 mars 2019  ·  12Commentaires  ·  Source: rust-rocksdb/rust-rocksdb

La fonction cf_handle est souvent appelée très fréquemment et sa mise en œuvre nécessite l'acquisition d'un verrou en lecture sur une carte sous-jacente. Si cela est appelé dans un hot-path, cela peut avoir des implications sur les performances. Nous devrions étudier le passage à une approche qui ne nécessite pas de verrou. Par exemple, nous pourrions faire en sorte que create_cf et drop_cf et toute autre fonction qui modifie la carte interne nécessitent une référence mutable à DB et rendent l'appelant responsable de l'acquisition de tous les verrous dans l'ordre pour muter le DB .

Commentaire le plus utile

Oui c'est le cas. Nous prévoyons de le publier dans un avenir proche.

Tous les 12 commentaires

comme ça?

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, dans le fork de paritech cf_handle est Copy , ce qui n'est pas techniquement sûr (on dirait OTOH qu'il est difficile d'en abuser), mais évite d'utiliser des verrous.

@hjiayz Oui, très similaire à ça.

Lorsque j'ai essayé de faire ce changement (c'est-à-dire prendre &mut self lors de la création/suppression de familles de colonnes), j'ai rencontré des problèmes avec la façon dont ColumnFamily est défini. Il stockera une référence mutable dans le PhantomData ce qui fait échouer un code comme celui-ci :

#[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"));
    }
}

L'erreur se produit lors d'un appel de méthode sur db qui prend &self , comme db.property_value_cf() et passe un ColumnFamily (qui stocke un &mut dans le db champ):

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

Je ne peux pas penser à un moyen très élégant de contourner cela, mais une option est de ne pas retourner un ColumnFamily de create_cf et de laisser plutôt le code de consommation le récupérer avec un appel à 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"));
    }
}

Est-ce que changer create_cf() pour retourner Result<(), Error> serait un changement acceptable ?

@dvdplm Ajouter des durées de vie à ColumnFamily a fini par être un peu un cauchemar d'un point de vue ergonomique. J'aimerais poursuivre une approche qui n'a pas besoin d'une durée de vie, mais qui ne court pas non plus le risque d'utiliser un pointeur de famille de colonnes après sa suppression. Ce changement aura probablement un impact sur la façon dont nous allons supprimer les verrous de cf_handle - vous ne verrez probablement pas ce problème.

D'accord avec @iSynaptic. Évidemment, retourner une référence à ColumnFamily n'est un moyen sûr que dans ce cas.

Peut-être que #298 peut être fusionné alors ?

314

Est-ce résolu par #314 ? Avez-vous l'intention de sortir si c'est le cas ?

Oui c'est le cas. Nous prévoyons de le publier dans un avenir proche.

@aleksuss quel est l'état de sa publication ? :)

@bkchr Je pense que nous le ferons la semaine prochaine.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

mvines picture mvines  ·  10Commentaires

zach-schoenberger picture zach-schoenberger  ·  5Commentaires

eupn picture eupn  ·  3Commentaires

valeriansaliou picture valeriansaliou  ·  4Commentaires

cetra3 picture cetra3  ·  9Commentaires