use std::alloc::{GlobalAlloc, Layout, System};
use std::path::PathBuf;
use std::sync::atomic::{AtomicUsize, Ordering};
use znippy_plugin_git::git_ops::{GitOps, GitStore};
use znippy_plugin_git::serve::{Caps, GitServe};
static LIVE: AtomicUsize = AtomicUsize::new(0);
static PEAK: AtomicUsize = AtomicUsize::new(0);
struct Counting;
impl Counting {
fn grew(by: usize) {
let now = LIVE.fetch_add(by, Ordering::Relaxed).saturating_add(by);
PEAK.fetch_max(now, Ordering::Relaxed);
}
fn shrank(by: usize) {
let _ = LIVE.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |v| {
Some(v.saturating_sub(by))
});
}
}
unsafe impl GlobalAlloc for Counting {
unsafe fn alloc(&self, l: Layout) -> *mut u8 {
let p = unsafe { System.alloc(l) };
if !p.is_null() {
Self::grew(l.size());
}
p
}
unsafe fn dealloc(&self, p: *mut u8, l: Layout) {
Self::shrank(l.size());
unsafe { System.dealloc(p, l) }
}
unsafe fn realloc(&self, p: *mut u8, l: Layout, new: usize) -> *mut u8 {
let q = unsafe { System.realloc(p, l, new) };
if !q.is_null() {
if new >= l.size() {
Self::grew(new - l.size());
} else {
Self::shrank(l.size() - new);
}
}
q
}
unsafe fn alloc_zeroed(&self, l: Layout) -> *mut u8 {
let p = unsafe { System.alloc_zeroed(l) };
if !p.is_null() {
Self::grew(l.size());
}
p
}
}
#[global_allocator]
static A: Counting = Counting;
struct Sink(u64);
impl std::io::Write for Sink {
fn write(&mut self, b: &[u8]) -> std::io::Result<usize> {
self.0 += b.len() as u64;
Ok(b.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
fn real_pack() -> Option<(PathBuf, Vec<u8>)> {
let mut best: Option<(u64, PathBuf)> = None;
for root in [
"/home/rickard/git",
"/home/rickard/scratch/gunnar-bench-fixtures",
] {
let Ok(repos) = std::fs::read_dir(root) else {
continue;
};
for repo in repos.flatten() {
for sub in [".git/objects/pack", "objects/pack"] {
let Ok(files) = std::fs::read_dir(repo.path().join(sub)) else {
continue;
};
for f in files.flatten() {
let p = f.path();
if p.extension().is_some_and(|e| e == "pack") {
let len = f.metadata().map(|m| m.len()).unwrap_or(0);
if len < (32 << 20) && best.as_ref().is_none_or(|(b, _)| len > *b) {
best = Some((len, p));
}
}
}
}
}
}
let (_, p) = best?;
let bytes = std::fs::read(&p).ok()?;
Some((p, bytes))
}
fn tmpdir(tag: &str) -> PathBuf {
let d = std::env::temp_dir().join(format!(
"znippy-emit-peak-{tag}-{}-{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_nanos())
.unwrap_or(0)
));
let _ = std::fs::remove_dir_all(&d);
std::fs::create_dir_all(&d).unwrap();
d
}
#[test]
fn serving_a_clone_does_not_allocate_the_pack_it_sends() {
let Some((path, pack)) = real_pack() else {
eprintln!("no real pack on this machine; nothing to measure");
return;
};
let dir = tmpdir("clone");
let store = GitStore::open(&dir, "rickard").expect("opening a store");
store.put_pack(&pack).expect("pushing the corpus pack");
store.absorb_pending().expect("absorbing it");
let oids = store.index().oids_in_order().expect("the store's own oids");
assert!(
oids.len() > 500,
"{} holds only {} objects — too few to tell a held pack from an addressed one",
path.display(),
oids.len()
);
let want: Vec<&[u8]> = oids.iter().map(Vec::as_slice).collect();
let mut warm = Sink(0);
store
.emit_pack(&want, &[], &Caps::modern(), &mut warm)
.expect("the warm-up clone");
let before = LIVE.load(Ordering::Acquire);
PEAK.store(before, Ordering::Release);
let mut sink = Sink(0);
let stats = store
.emit_pack(&want, &[], &Caps::modern(), &mut sink)
.expect("serving the clone");
let peak = PEAK.load(Ordering::Acquire).saturating_sub(before);
assert_eq!(stats.bytes, sink.0, "the receipt must be what was written");
assert_eq!(
stats.objects,
oids.len() as u64,
"a whole-repository clone must send every object"
);
assert_eq!(
stats.recompressed, 0,
"a whole-repository clone re-deflates nothing, so every entry is a copy and every copy \
must have come from an extent"
);
const PER_OBJECT_CEILING: u64 = 512;
let per_object = peak as u64 / stats.objects;
let ratio = peak as f64 / stats.bytes as f64;
eprintln!(
"{}: {} objects, {} pack bytes, peak {peak} live heap bytes — {per_object} B per object, \
{ratio:.2}x the pack. The mapping is NOT counted: it is page cache, not heap.",
path.display(),
stats.objects,
stats.bytes,
);
assert!(
per_object < PER_OBJECT_CEILING,
"serving {} objects held a peak of {peak} live heap bytes — {per_object} B per object \
against a {PER_OBJECT_CEILING} B ceiling. An entry that owns its payload holds the pack; \
an entry that addresses it does not.",
stats.objects
);
let _ = std::fs::remove_dir_all(&dir);
}