cf_handle
関数は頻繁に呼び出され、その実装には、基になるマップへの読み取りロックを取得する必要があります。 これがホットパスで呼び出されると、パフォーマンスに影響を与える可能性があります。 これをロックを必要としないアプローチに切り替えることを検討する必要があります。 たとえば、 create_cf
とdrop_cf
を作成し、内部マップを変更するその他の関数にはDB
への変更可能な参照が必要であり、呼び出し元にロックを順番に取得する責任を負わせることができます。 DB
ます。
このような?
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"));
}
}
かかるDBにメソッド呼び出し際にエラーが起こる&self
ように、 db.property_value_cf()
とを渡すColumnFamily
(この店舗&mut
でdb
フィールド):
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で解決しましたか? もしそうなら、リリースする予定はありますか?
はい、そうです。 近いうちにリリースする予定です。
@aleksussそれをリリースする状況はどうですか? :)
@bkchr来週やろうと思います。
最も参考になるコメント
はい、そうです。 近いうちにリリースする予定です。