Rust-rocksdb: Machen Sie `cf_handle` frei von Sperren

Erstellt am 13. März 2019  ·  12Kommentare  ·  Quelle: rust-rocksdb/rust-rocksdb

Die Funktion cf_handle wird oft sehr häufig aufgerufen und ihre Implementierung erfordert den Erwerb einer Lesesperre für eine zugrunde liegende Karte. Wenn dies in einem Hot-Path aufgerufen wird, kann dies Auswirkungen auf die Leistung haben. Wir sollten untersuchen, ob dies auf einen Ansatz umgestellt wird, der keine Sperre erfordert. Zum Beispiel könnten wir create_cf und drop_cf und jede andere Funktion, die die interne Map verändert, eine veränderliche Referenz auf DB erfordern und den Aufrufer dafür verantwortlich machen, alle Sperren in der richtigen Reihenfolge zu erwerben um das DB zu mutieren.

Hilfreichster Kommentar

Ja, so ist es. Wir planen, es in naher Zukunft zu veröffentlichen.

Alle 12 Kommentare

so was?

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, in Paritechs Fork cf_handle ist Copy , was technisch nicht sicher ist (OTOH würde argumentieren, dass es schwer zu missbrauchen ist), aber die Verwendung von Sperren vermeidet.

@hjiayz Ja, sehr ähnlich.

Als ich versuchte, diese Änderung vorzunehmen (zB &mut self beim Erstellen/Ablegen von Spaltenfamilien nehmen), stieß ich auf Probleme mit der Definition von ColumnFamily . Es wird eine veränderliche Referenz in PhantomData gespeichert, wodurch Code wie dieser fehlschlägt:

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

Der Fehler passiert , wenn ein Methodenaufruf zu db macht das braucht &self , wie beispielsweise db.property_value_cf() und Weitergabe in einem ColumnFamily (die speichern ein &mut im db Feld):

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

Ich kann mir keinen sehr eleganten Weg vorstellen, aber eine Möglichkeit besteht darin, kein ColumnFamily von create_cf und es stattdessen von konsumierendem Code mit einem Aufruf von cf_handle() holen zu lassen.

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

Wäre die Änderung von create_cf() in Result<(), Error> eine akzeptable Änderung?

@dvdplm Das Hinzufügen von Lebensdauern zu ColumnFamily war aus ergonomischer Sicht ein Albtraum. Ich möchte einen Ansatz verfolgen, der keine Lebensdauer benötigt, aber auch nicht das Risiko eingeht, einen Spaltenfamilienzeiger zu verwenden, nachdem er gelöscht wurde. Diese Änderung wird sich wahrscheinlich darauf auswirken, wie wir Sperren von cf_handle entfernen - Sie werden dieses Problem wahrscheinlich nicht sehen.

Stimme @iSynaptic zu. Offensichtlich ist das Zurückgeben einer Referenz auf ColumnFamily nur in diesem Fall ein sicherer Weg.

Vielleicht kann #298 dann zusammengeführt werden?

314

Ist es von #314 gelöst? Gibt es Pläne für eine Veröffentlichung, wenn ja?

Ja, so ist es. Wir planen, es in naher Zukunft zu veröffentlichen.

@aleksuss Wie ist der Status der Veröffentlichung? :)

@bkchr Ich denke, wir werden es nächste Woche tun.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

iSynaptic picture iSynaptic  ·  31Kommentare

f41gh7 picture f41gh7  ·  4Kommentare

rohitjoshi picture rohitjoshi  ·  10Kommentare

iSynaptic picture iSynaptic  ·  5Kommentare

zach-schoenberger picture zach-schoenberger  ·  7Kommentare