Rust-rocksdb: Tornar `cf_handle` sem bloqueio

Criado em 13 mar. 2019  ·  12Comentários  ·  Fonte: rust-rocksdb/rust-rocksdb

A função cf_handle é freqüentemente chamada com muita freqüência e sua implementação requer a aquisição de um bloqueio de leitura para um mapa subjacente. Se for chamado em um caminho ativo, pode ter implicações de desempenho. Devemos investigar como mudar isso para uma abordagem que não exija um bloqueio. Por exemplo, poderíamos fazer create_cf e drop_cf e qualquer outra função que modifique o mapa interno exigir uma referência mutável a DB e tornar o chamador responsável por adquirir quaisquer bloqueios em ordem para transformar DB .

Comentários muito úteis

Sim, ele é. Planejamos lançá-lo em um futuro próximo.

Todos 12 comentários

assim?

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, no fork da paritech cf_handle é Copy , o que não é tecnicamente seguro (OTOH diria que é difícil de usar indevidamente), mas evita o uso de bloqueios.

@hjiayz Sim, muito parecido com isso.

Quando tentei fazer essa alteração (ou seja, pegar &mut self ao criar / descartar famílias de colunas), tive problemas com a maneira ColumnFamily é definido. Ele armazenará uma referência mutável em PhantomData que faz com que um código como este falhe:

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

O erro acontece ao fazer uma chamada de método no banco de dados que leva &self , como db.property_value_cf() e passando um ColumnFamily (que armazena um &mut no 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

Não consigo pensar em uma maneira muito elegante de contornar isso, mas uma opção é não retornar um ColumnFamily de create_cf e, em vez disso, deixar o código consumir buscá-lo com uma chamada para 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"));
    }
}

Mudar create_cf() para retornar Result<(), Error> seria uma mudança aceitável?

@dvdplm Adicionar vidas a ColumnFamily acabou sendo um pesadelo do ponto de vista ergonômico. Eu gostaria de seguir uma abordagem que não precisa de uma vida inteira, mas também não corre o risco de usar um ponteiro de família de colunas depois de ser excluído. Essa mudança provavelmente afetará a forma como removemos os bloqueios de cf_handle - você provavelmente não verá esse problema.

Concorde com @iSynaptic. Obviamente, retornar uma referência a ColumnFamily é uma maneira segura apenas neste caso.

Talvez # 298 possa ser mesclado, então?

314

Foi resolvido por # 314? Algum plano de lançamento em caso afirmativo?

Sim, ele é. Planejamos lançá-lo em um futuro próximo.

@aleksuss qual é o status de liberá-lo? :)

@bkchr Acho que faremos isso na próxima semana.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

alex88 picture alex88  ·  7Comentários

spacejam picture spacejam  ·  3Comentários

valeriansaliou picture valeriansaliou  ·  4Comentários

yiyanwannian picture yiyanwannian  ·  6Comentários

eupn picture eupn  ·  3Comentários