Skip to main content

range_timing/
range_timing.rs

1//! Time ahead/behind counts and range walks for explicit commit pairs.
2//! Arguments: repository, rounds, then one or more `LEFT...RIGHT` pairs of full commit IDs.
3//! Prints, per pair, the counts and the best round for `ahead_behind(LEFT, RIGHT)` and for
4//! `walk_range([RIGHT], [LEFT])` (`git rev-list LEFT..RIGHT`). Compare against
5//! `git rev-list --left-right --count LEFT...RIGHT` and `git rev-list --count LEFT..RIGHT`.
6//! Uses trusted history limits, since long Linux ranges explore more than the default bound.
7use std::hint::black_box;
8use std::time::{Duration, Instant};
9
10use girt::{HistoryLimits, ObjectId, PackLimits, Repository};
11
12fn main() -> Result<(), Box<dyn std::error::Error>> {
13    let mut args = std::env::args().skip(1);
14    let path = args.next().ok_or("expected repository path")?;
15    let rounds: usize = args.next().ok_or("expected number of rounds")?.parse()?;
16    let start = Instant::now();
17    let repo = Repository::open(path)?;
18    let objects = repo.objects_with(PackLimits::trusted())?;
19    println!("open {:.1} ms", ms(start.elapsed()));
20    for pair in args {
21        let (left, right) = pair.split_once("...").ok_or("expected LEFT...RIGHT")?;
22        let (left, right): (ObjectId, ObjectId) = (left.parse()?, right.parse()?);
23        let mut counts = None;
24        let mut best_counts = Duration::MAX;
25        let mut walked = 0;
26        let mut best_walk = Duration::MAX;
27        for _ in 0..rounds {
28            let start = Instant::now();
29            counts = Some(black_box(objects.ahead_behind_with(
30                left,
31                right,
32                HistoryLimits::trusted(),
33            )?));
34            best_counts = best_counts.min(start.elapsed());
35            let start = Instant::now();
36            walked =
37                black_box(objects.walk_range_with(&[right], &[left], HistoryLimits::trusted())?)
38                    .len();
39            best_walk = best_walk.min(start.elapsed());
40        }
41        let counts = counts.ok_or("expected at least one round")?;
42        println!(
43            "{pair}: ahead {} behind {} in {:.2} ms; range {walked} in {:.2} ms",
44            counts.ahead,
45            counts.behind,
46            ms(best_counts),
47            ms(best_walk),
48        );
49    }
50    Ok(())
51}
52
53fn ms(duration: Duration) -> f64 {
54    duration.as_secs_f64() * 1e3
55}