midx_lookup_timing/
midx_lookup_timing.rs1use std::hint::black_box;
9use std::time::Instant;
10
11use girt::{ObjectId, Repository};
12
13fn main() -> Result<(), Box<dyn std::error::Error>> {
14 let mut args = std::env::args().skip(1);
15 let path = args.next().ok_or("expected repository path")?;
16 let list = args.next().ok_or("expected object-ID list path")?;
17 let rounds: usize = args.next().ok_or("expected number of rounds")?.parse()?;
18 let mode = args.next().unwrap_or_else(|| "read".to_owned());
19 let ids = std::fs::read_to_string(list)?
20 .lines()
21 .map(str::parse)
22 .collect::<Result<Vec<ObjectId>, _>>()?;
23 let repo = Repository::open(path)?;
24 let start = Instant::now();
25 let objects = repo.objects()?;
26 let opening = start.elapsed();
27 let packs: Vec<_> = objects.packs().collect();
28 let bytes = if mode == "midx" {
29 std::fs::read(repo.object_dir().join("pack/multi-pack-index"))?
30 } else {
31 Vec::new()
32 };
33 let midx = if mode == "midx" {
34 Some(girt::multi_pack_index::MultiPackIndex::parse(
35 &bytes,
36 repo.object_format(),
37 )?)
38 } else {
39 None
40 };
41 let start = Instant::now();
42 let mut found = 0_usize;
43 for _ in 0..rounds {
44 for id in &ids {
45 let present = match mode.as_str() {
46 "read" => {
47 black_box(objects.read(*id)?.ok_or("object absent")?);
48 true
49 }
50 "contains" => objects.contains(*id)?,
51 "index-scan" => scan(&packs, *id)?,
52 "midx" => midx.as_ref().ok_or("index absent")?.find(*id).is_some(),
53 _ => return Err("expected read, contains, index-scan or midx".into()),
54 };
55 found += usize::from(black_box(present));
56 }
57 }
58 println!(
59 "objects={} rounds={rounds} mode={mode} found={found} open_ns={} read_ns={}",
60 ids.len(),
61 opening.as_nanos(),
62 start.elapsed().as_nanos(),
63 );
64 Ok(())
65}
66
67fn scan(packs: &[girt::IndexedPack<'_>], id: ObjectId) -> Result<bool, girt::ObjectReadError> {
68 for pack in packs {
69 if pack.contains(id)? {
70 return Ok(true);
71 }
72 }
73 Ok(false)
74}