La fonction cf_handle
est souvent appelée très fréquemment et sa mise en œuvre nécessite l'acquisition d'un verrou en lecture sur une carte sous-jacente. Si cela est appelé dans un hot-path, cela peut avoir des implications sur les performances. Nous devrions étudier le passage à une approche qui ne nécessite pas de verrou. Par exemple, nous pourrions faire en sorte que create_cf
et drop_cf
et toute autre fonction qui modifie la carte interne nécessitent une référence mutable à DB
et rendent l'appelant responsable de l'acquisition de tous les verrous dans l'ordre pour muter le DB
.
comme ça?
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, dans le fork de paritech cf_handle
est Copy
, ce qui n'est pas techniquement sûr (on dirait OTOH qu'il est difficile d'en abuser), mais évite d'utiliser des verrous.
@hjiayz Oui, très similaire à ça.
Lorsque j'ai essayé de faire ce changement (c'est-à-dire prendre &mut self
lors de la création/suppression de familles de colonnes), j'ai rencontré des problèmes avec la façon dont ColumnFamily
est défini. Il stockera une référence mutable dans le PhantomData
ce qui fait échouer un code comme celui-ci :
#[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"));
}
}
L'erreur se produit lors d'un appel de méthode sur db qui prend &self
, comme db.property_value_cf()
et passe un ColumnFamily
(qui stocke un &mut
dans le db
champ):
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
Je ne peux pas penser à un moyen très élégant de contourner cela, mais une option est de ne pas retourner un ColumnFamily
de create_cf
et de laisser plutôt le code de consommation le récupérer avec un appel à 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"));
}
}
Est-ce que changer create_cf()
pour retourner Result<(), Error>
serait un changement acceptable ?
@dvdplm Ajouter des durées de vie à ColumnFamily
a fini par être un peu un cauchemar d'un point de vue ergonomique. J'aimerais poursuivre une approche qui n'a pas besoin d'une durée de vie, mais qui ne court pas non plus le risque d'utiliser un pointeur de famille de colonnes après sa suppression. Ce changement aura probablement un impact sur la façon dont nous allons supprimer les verrous de cf_handle
- vous ne verrez probablement pas ce problème.
D'accord avec @iSynaptic. Évidemment, retourner une référence à ColumnFamily
n'est un moyen sûr que dans ce cas.
Peut-être que #298 peut être fusionné alors ?
Est-ce résolu par #314 ? Avez-vous l'intention de sortir si c'est le cas ?
Oui c'est le cas. Nous prévoyons de le publier dans un avenir proche.
@aleksuss quel est l'état de sa publication ? :)
@bkchr Je pense que nous le ferons la semaine prochaine.
Commentaire le plus utile
Oui c'est le cas. Nous prévoyons de le publier dans un avenir proche.