Rust-rocksdb: Сделайте cf_handle свободным от блокировок

Созданный на 13 мар. 2019  ·  12Комментарии  ·  Источник: rust-rocksdb/rust-rocksdb

Функция cf_handle часто вызывается очень часто, и для ее реализации требуется блокировка чтения для базовой карты. Если это вызывается по горячему пути, это может повлиять на производительность. Мы должны изучить возможность переключения этого подхода на подход, не требующий блокировки. Например, мы могли бы сделать create_cf и drop_cf и любую другую функцию, изменяющую внутреннюю карту, потребовать изменяемую ссылку на DB и сделать вызывающего ответственным за получение любых блокировок по порядку. чтобы изменить DB .

Самый полезный комментарий

Да, это так. Мы планируем выпустить его в ближайшее время.

Все 12 Комментарий

нравится?

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, в вилке paritech cf_handle - это Copy , что технически небезопасно (можно утверждать, что OTOH трудно использовать неправильно), но избегает использования блокировок.

@hjiayz Да, очень похоже на это.

Когда я попытался внести это изменение (т.е. взять &mut self при создании / удалении семейств столбцов), я столкнулся с проблемами, связанными со способом определения ColumnFamily . Он сохранит изменяемую ссылку в PhantomData что приведет к сбою такого кода:

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

Ошибка возникает при вызове метода в базе данных, который принимает &self , например db.property_value_cf() и передает ColumnFamily (который сохраняет &mut в db field):

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

Я не могу придумать очень элегантный способ обойти это, но один из вариантов - не возвращать ColumnFamily из create_cf и вместо этого позволить потребляющему коду получить его с вызовом 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"));
    }
}

Будет ли изменение create_cf() на возврат Result<(), Error> приемлемым изменением?

@dvdplm Добавление времени жизни к ColumnFamily конечном итоге стало кошмаром с эргономической точки зрения. Я хотел бы придерживаться подхода, который не требует времени жизни, но также не сопряжен с риском использования указателя семейства столбцов после его удаления. Это изменение, вероятно, повлияет на то, как мы будем снимать блокировки с cf_handle - вы, вероятно, не увидите этой проблемы.

Согласитесь с @iSynaptic. Очевидно, что возврат ссылки на ColumnFamily безопасен только в этом случае.

Может, тогда # 298 можно будет объединить?

314

Это решено # 314? Есть ли планы выпустить, если так?

Да, это так. Мы планируем выпустить его в ближайшее время.

@aleksuss, каков статус его выпуска? :)

@bkchr Думаю, мы сделаем это на следующей неделе.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

iSynaptic picture iSynaptic  ·  5Комментарии

yiyanwannian picture yiyanwannian  ·  6Комментарии

eupn picture eupn  ·  3Комментарии

valeriansaliou picture valeriansaliou  ·  4Комментарии

rrichardson picture rrichardson  ·  7Комментарии