Skip to content

Commit

Permalink
Add a crude cache of manifest trees
Browse files Browse the repository at this point in the history
This compensates the loss of the minimal caching we had before a5579cd and
makes unbundling faster than ever before.

We'll see later for better APIs and/or better strategies.
  • Loading branch information
glandium committed Nov 6, 2023
1 parent 3a5aa80 commit 0b56b42
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 2 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ version = "1"
version = "0.4"
features = ["std"]

[dependencies.lru]
version = "0.12"
default-features = false

[dependencies.regex]
version = "1"
default-features = false
Expand Down
42 changes: 41 additions & 1 deletion src/cinnabar/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::cell::RefCell;
use std::cmp;
use std::io::{self, Write};
use std::num::NonZeroUsize;

use either::Either;
use lru::LruCache;

use crate::git::{git_oid_type, CommitId, MalformedTree, TreeId, TreeIsh};
use crate::hg::{HgFileAttr, HgFileId, ManifestEntry};
Expand All @@ -31,11 +35,47 @@ impl TreeIsh for GitManifestId {
}
}

#[derive(Clone)]
pub struct GitManifestTree(RawTree);

thread_local! {
static MANIFEST_TREE_CACHE: RefCell<(LruCache<GitManifestTreeId, GitManifestTree>, usize, usize)> = RefCell::new((LruCache::unbounded(), 0, 0));
}

impl GitManifestTree {
pub fn read(oid: GitManifestTreeId) -> Option<GitManifestTree> {
RawTree::read(oid.into()).map(Self)
MANIFEST_TREE_CACHE.with(|cache| {
let (lru_cache, queries, misses) = &mut *cache.borrow_mut();
*queries += 1;
let result = lru_cache
.try_get_or_insert(oid, || {
*misses += 1;
RawTree::read(oid.into()).map(Self).ok_or(())
})
.ok()
.cloned();
let queries_limit = cmp::max(100, lru_cache.len() / 2);
if *queries >= queries_limit {
let miss_rate = *misses / (*queries / 10);
if (lru_cache.cap() == NonZeroUsize::MAX) || miss_rate >= 7 {
lru_cache.resize(
NonZeroUsize::new(lru_cache.len() + lru_cache.len() / 2 + 1).unwrap(),
);
}
debug!(
target: "manifesttreecache",
"cap: {}, len: {} ; {} misses in the last {} queries ({:.1}%)",
lru_cache.cap(),
lru_cache.len(),
*misses,
*queries,
(*misses as f64) * 100.0 / (*queries as f64)
);
*queries = 0;
*misses = 0;
}
result
})
}

pub fn read_treeish<T: TreeIsh<TreeId = GitManifestTreeId>>(t: T) -> Option<GitManifestTree> {
Expand Down
14 changes: 13 additions & 1 deletion src/libgit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use std::ffi::{c_void, CStr, CString, OsStr, OsString};
use std::fmt;
use std::io::{self, Write};
use std::mem;
use std::num::ParseIntError;
use std::os::raw::{c_char, c_int, c_long, c_uint, c_ulong, c_ushort};
use std::str::FromStr;
Expand Down Expand Up @@ -313,6 +314,17 @@ impl RawObject {
}
}

impl Clone for RawObject {
fn clone(&self) -> Self {
let mut cloned = strbuf::new();
cloned.extend_from_slice(self.as_bytes());
let buf = cloned.as_ptr() as *const _;
let len = cloned.as_bytes().len();
mem::forget(cloned);
RawObject { buf, len }
}
}

impl Drop for RawObject {
fn drop(&mut self) {
unsafe {
Expand All @@ -323,7 +335,7 @@ impl Drop for RawObject {

macro_rules! raw_object {
($t:ident | $oid_type:ident => $name:ident) => {
#[derive(Deref)]
#[derive(Deref, Clone)]
pub struct $name(RawObject);

impl $name {
Expand Down

0 comments on commit 0b56b42

Please sign in to comment.