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
我想不出一个非常优雅的方法来解决这个问题,但一个选择是不从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我想我们会在下周这样做。
最有用的评论
是的。 我们计划在不久的将来发布它。