Add LRU cache for external object ID lookup

This commit is contained in:
Alex Good 2021-12-27 18:13:51 +00:00
parent 1f50c386b8
commit 8441fccea2
No known key found for this signature in database
GPG key ID: EFB9C073F4D525AE
4 changed files with 46 additions and 5 deletions

View file

@ -26,6 +26,7 @@ tinyvec = { version = "^1.5.1", features = ["alloc"] }
unicode-segmentation = "1.7.1"
serde = { version = "^1.0", features=["derive"] }
dot = { version = "0.1.4", optional = true }
lru = "^0.7.1"
[dependencies.web-sys]
version = "^0.3.55"

View file

@ -21,9 +21,12 @@ impl ExternalOpId {
})
}
pub(crate) fn into_opid(&self, metadata: &mut OpSetMetadata) -> OpId {
let actor = metadata.actors.cache(self.actor.clone());
OpId::new(self.counter, actor)
pub(crate) fn counter(&self) -> u64 {
self.counter
}
pub(crate) fn actor(&self) -> &ActorId {
&self.actor
}
}

View file

@ -1110,7 +1110,7 @@ impl Automerge {
}
fn import_opid(&self, opid: &OpId) -> InternalOpId {
opid.into_opid(&mut *self.ops.m.borrow_mut())
self.ops.m.borrow_mut().import_opid(opid)
}
fn export_opid(&self, opid: &InternalOpId) -> Option<OpId> {

View file

@ -1,11 +1,15 @@
use crate::op_tree::OpTreeInternal;
use crate::query::TreeQuery;
use crate::{ActorId, IndexedCache, Key, types::{ObjId, OpId}, Op};
use crate::external_types::ExternalOpId;
use fxhash::FxBuildHasher;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt::Debug;
const EXTERNAL_OP_CACHE_SIZE: usize = 100;
pub(crate) type OpSet = OpSetInternal<16>;
@ -26,6 +30,7 @@ impl<const B: usize> OpSetInternal<B> {
m: Rc::new(RefCell::new(OpSetMetadata {
actors: IndexedCache::new(),
props: IndexedCache::new(),
external_op_cache: lru::LruCache::with_hasher(EXTERNAL_OP_CACHE_SIZE, FxBuildHasher::default())
})),
}
}
@ -150,12 +155,33 @@ impl<'a, const B: usize> Iterator for Iter<'a, B> {
}
}
#[derive(Clone, Debug)]
pub(crate) struct OpSetMetadata {
pub actors: IndexedCache<ActorId>,
pub props: IndexedCache<String>,
external_op_cache: lru::LruCache<ExternalOpId, OpId, FxBuildHasher>,
}
impl Debug for OpSetMetadata {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OpSetMetadata")
.field("actors", &self.actors)
.field("props", &self.props)
.field("external_op_cache", &format_args!("LruCache with {} keys", self.external_op_cache.len()))
.finish()
}
}
impl Clone for OpSetMetadata {
fn clone(&self) -> Self {
OpSetMetadata {
actors: self.actors.clone(),
props: self.props.clone(),
external_op_cache: lru::LruCache::with_hasher(EXTERNAL_OP_CACHE_SIZE, FxBuildHasher::default()),
}
}
}
impl OpSetMetadata {
pub fn key_cmp(&self, left: &Key, right: &Key) -> Ordering {
match (left, right) {
@ -167,6 +193,17 @@ impl OpSetMetadata {
pub fn lamport_cmp<S: SuccinctLamport>(&self, left: S, right: S) -> Ordering {
S::cmp(self, left, right)
}
pub fn import_opid(&mut self, ext_opid: &ExternalOpId) -> OpId {
if let Some(opid) = self.external_op_cache.get(ext_opid) {
*opid
} else {
let actor = self.actors.cache(ext_opid.actor().clone());
let opid = OpId::new(ext_opid.counter(), actor);
self.external_op_cache.put(ext_opid.clone(), opid);
opid
}
}
}
/// Lamport timestamps which don't contain their actor ID directly and therefore need access to