Rust-rocksdb: `cf_handle`をロックフリーにする

作成日 2019年03月13日  ·  12コメント  ·  ソース: rust-rocksdb/rust-rocksdb

cf_handle関数は頻繁に呼び出され、その実装には、基になるマップへの読み取りロックを取得する必要があります。 これがホットパスで呼び出されると、パフォーマンスに影響を与える可能性があります。 これをロックを必要としないアプローチに切り替えることを検討する必要があります。 たとえば、 create_cfdrop_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_handleCopyであり、技術的に安全ではありません(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"));
    }
}

かかるDBにメソッド呼び出し際にエラーが起こる&selfように、 db.property_value_cf()とを渡すColumnFamily (この店舗&mutdbフィールド):

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

これを回避するための非常にエレガントな方法は考えられませんが、1つのオプションは、 ColumnFamilyからcreate_cf ColumnFamilyを返さず、代わりに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 評価