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.
  • Loading branch information
glandium committed Nov 5, 2023
1 parent 3a5aa80 commit a5005ea
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 a5005ea

Please sign in to comment.