Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ This is a reference implementation of the gmeta spec ([docs](https://schacon.git
- Use `time` crate (workspace dep) for date/time — no manual epoch math or magic constants like `86400`.
- Prefer guard clauses (early returns) over nested `if` blocks.
- Prefer iterators/combinators over manual loops. Use `Cow<'_, str>` when allocation is conditional.
- **No banner/separator comments.** Do not use decorative divider comments like `// ── Section ───`. Use normal `//` comments or doc comments to explain *why*, not to visually partition files.

## Dependencies

Expand Down
5 changes: 0 additions & 5 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ pub struct Cli {

#[derive(Subcommand)]
pub enum Commands {
// ── Read / Write (display_order 1x) ─────────────────────────────────────
/// Set a metadata value
#[command(display_order = 10)]
Set {
Expand Down Expand Up @@ -152,7 +151,6 @@ pub enum Commands {
value: String,
},

// ── Inspect (display_order 2x) ──────────────────────────────────────────
/// Show commit details and associated metadata
#[command(display_order = 20)]
Show {
Expand Down Expand Up @@ -199,7 +197,6 @@ pub enum Commands {
metadata_only: bool,
},

// ── Sync (display_order 3x) ─────────────────────────────────────────────
/// Serialize metadata to Git ref
#[command(display_order = 30)]
Serialize {
Expand Down Expand Up @@ -285,7 +282,6 @@ pub enum Commands {
debounce: u64,
},

// ── Maintenance (display_order 4x) ──────────────────────────────────────
/// Get or set project configuration (meta:* keys)
#[command(display_order = 40)]
Config {
Expand Down Expand Up @@ -332,7 +328,6 @@ pub enum Commands {
#[command(display_order = 44)]
Teardown,

// ── Benchmarks (hidden) ─────────────────────────────────────────────────
/// Benchmark read performance across all stored keys
#[command(hide = true)]
Bench,
Expand Down
43 changes: 0 additions & 43 deletions src/commands/bench/fanout_bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use std::path::PathBuf;
use std::sync::Arc;
use std::time::Instant;

// ── ANSI colours ─────────────────────────────────────────────────────────────
const RESET: &str = "\x1b[0m";
const BOLD: &str = "\x1b[1m";
const DIM: &str = "\x1b[2m";
Expand All @@ -27,9 +26,6 @@ const GREEN: &str = "\x1b[32m";
const RED: &str = "\x1b[31m";
const BLUE: &str = "\x1b[34m";
const MAGENTA: &str = "\x1b[35m";

// ── Fanout schemes ────────────────────────────────────────────────────────────

#[derive(Clone, Copy, Debug)]
pub enum Scheme {
First2, // commit/{aa}/{full_sha}
Expand Down Expand Up @@ -64,9 +60,6 @@ impl Scheme {
}
}
}

// ── Tree builder (mirrors serialize.rs) ──────────────────────────────────────

#[derive(Default)]
struct Dir {
files: BTreeMap<String, Vec<u8>>,
Expand Down Expand Up @@ -231,7 +224,6 @@ fn write_commit(repo: &Repository, tree_oid: Oid, parent_oid: Option<Oid>) -> Re
Ok(repo.commit(None, &sig, &sig, "bench", &tree, &parent_refs)?)
}

// ── SHA generation ────────────────────────────────────────────────────────────
//
// Deterministic fake SHAs: we hash an integer with a simple xor-shift so every
// "SHA" looks like a real 40-hex-char commit hash and has uniform distribution
Expand All @@ -249,9 +241,6 @@ fn fake_sha(n: u64) -> String {
.wrapping_add(0x62b821756295c58d);
format!("{:016x}{:016x}{:08x}", x, y, (x ^ y) as u32)
}

// ── Pretty printing ───────────────────────────────────────────────────────────

fn print_header(label: &str) {
println!(
"\n{}{} ══════════════════════════════════════════════{}\n",
Expand All @@ -271,19 +260,13 @@ fn bar(value: f64, max: f64, width: usize, color: &str) -> String {
let filled = ((value / max) * width as f64).round() as usize;
format!("{}{}{}", color, "█".repeat(filled.min(width)), RESET)
}

// ── Diff: count paths present in new_tree but not base_tree, or with different OID ──

fn diff_trees(repo: &Repository, base_oid: Oid, new_oid: Oid) -> Result<usize> {
let base_tree = repo.find_tree(base_oid)?;
let new_tree = repo.find_tree(new_oid)?;
let mut diff_opts = git2::DiffOptions::new();
let diff = repo.diff_tree_to_tree(Some(&base_tree), Some(&new_tree), Some(&mut diff_opts))?;
Ok(diff.deltas().count())
}

// ── Pack size ─────────────────────────────────────────────────────────────────

fn pack_size_bytes(repo_path: &std::path::Path) -> Result<u64> {
let pack_dir = repo_path.join("objects").join("pack");
let mut total = 0u64;
Expand Down Expand Up @@ -331,9 +314,6 @@ fn count_loose_objects(repo_path: &std::path::Path) -> Result<usize> {
}
Ok(count)
}

// ── Per-scheme benchmark ──────────────────────────────────────────────────────

struct SchemeResult {
scheme: Scheme,
/// Batch write: incremental tree update inserting SAMPLE entries at once
Expand Down Expand Up @@ -370,7 +350,6 @@ fn bench_scheme(
std::fs::create_dir_all(&repo_path)?;
let repo = Repository::init_bare(&repo_path)?;

// ── 1. Build base tree with n_base objects (full build, done once) ────────
let base_files: BTreeMap<String, Vec<u8>> = shas[..n_base]
.iter()
.map(|sha| (scheme.shard_path(sha), entry_content(sha)))
Expand All @@ -390,7 +369,6 @@ fn bench_scheme(
// Commit the base tree so sequential writes have a real parent chain.
let base_commit_oid = write_commit(&repo, base_tree_oid, None)?;

// ── 2a. Write test — BATCH ────────────────────────────────────────────────
// Incremental: apply SAMPLE new entries onto the existing base tree in one
// shot. Only the shard subtrees touched by the new entries are rebuilt;
// everything else is reused by OID. This is what a correct gmeta serialize
Expand All @@ -416,7 +394,6 @@ fn bench_scheme(
RESET
));

// ── 2b. Write test — SEQUENTIAL ───────────────────────────────────────────
// Add 1 entry, write an incremental tree, write a commit with the previous
// commit as parent — repeat SAMPLE times. Models frequent single-change
// serializes (e.g. one gmeta set → serialize per user action).
Expand All @@ -439,7 +416,6 @@ fn bench_scheme(
(write_seq_secs * 1_000_000.0 / SAMPLE as f64) as u64,
));

// ── 3. Read benchmark ─────────────────────────────────────────────────────
let read_shas: Vec<&String> = shas[..n_base]
.iter()
.step_by((n_base / SAMPLE).max(1))
Expand All @@ -465,7 +441,6 @@ fn bench_scheme(
read_shas.len()
));

// ── 4. Diff benchmark ─────────────────────────────────────────────────────
let t0 = Instant::now();
let diff_count = diff_trees(&repo, base_tree_oid, batch_tree_oid)?;
let diff_secs = t0.elapsed().as_secs_f64();
Expand All @@ -477,7 +452,6 @@ fn bench_scheme(
diff_count
));

// ── 5. Pack size ──────────────────────────────────────────────────────────
let loose_before = count_loose_objects(&repo_path)?;
let t0 = Instant::now();
run_git_gc(&repo_path)?;
Expand Down Expand Up @@ -506,9 +480,6 @@ fn bench_scheme(
log,
})
}

// ── Report ────────────────────────────────────────────────────────────────────

fn print_report(results: &[SchemeResult], n_base: usize) {
print_header("RESULTS SUMMARY");

Expand Down Expand Up @@ -537,7 +508,6 @@ fn print_report(results: &[SchemeResult], n_base: usize) {
let max_loose = maxu!(loose_objects_before_gc);
let max_diff = maxf!(diff_secs);

// ── Write A: batch ────────────────────────────────────────────────────────
println!(
"{}Write A — batch: {} new entries → 1 incremental tree (into {}-object base){}",
BOLD, SAMPLE, n_base, RESET
Expand All @@ -558,7 +528,6 @@ fn print_report(results: &[SchemeResult], n_base: usize) {
);
}

// ── Write B: sequential ───────────────────────────────────────────────────
println!(
"\n{}Write B — sequential: 1 entry → incremental tree → commit × {} (chained parents){}",
BOLD, SAMPLE, RESET
Expand All @@ -583,7 +552,6 @@ fn print_report(results: &[SchemeResult], n_base: usize) {
);
}

// ── Read throughput ───────────────────────────────────────────────────────
println!("\n{}Read 1 000 objects by known SHA{}", BOLD, RESET);
println!(
" {}(lower = faster; tree.get_path() walk per lookup){}",
Expand All @@ -601,7 +569,6 @@ fn print_report(results: &[SchemeResult], n_base: usize) {
);
}

// ── Diff speed ────────────────────────────────────────────────────────────
println!("\n{}Diff base tree vs base + 1 000 changes{}", BOLD, RESET);
println!(
" {}(lower = faster; git diff_tree_to_tree){} [changed blobs: {}{}{}]",
Expand All @@ -623,7 +590,6 @@ fn print_report(results: &[SchemeResult], n_base: usize) {
);
}

// ── Pack size ─────────────────────────────────────────────────────────────
println!(
"\n{}Pack file size (after git gc --aggressive){}",
BOLD, RESET
Expand All @@ -642,7 +608,6 @@ fn print_report(results: &[SchemeResult], n_base: usize) {
);
}

// ── Loose object count ────────────────────────────────────────────────────
println!("\n{}Loose object count (before gc){}", BOLD, RESET);
println!(
" {}(tree objects + blob objects written to ODB){}",
Expand All @@ -665,7 +630,6 @@ fn print_report(results: &[SchemeResult], n_base: usize) {
);
}

// ── Per-object read latency ───────────────────────────────────────────────
println!(
"\n{}Per-object read latency (avg over 1 000){}",
BOLD, RESET
Expand All @@ -681,7 +645,6 @@ fn print_report(results: &[SchemeResult], n_base: usize) {
);
}

// ── Verdict ───────────────────────────────────────────────────────────────
println!("\n{} ── Verdict ──{} (bucket counts: ", BOLD, RESET);
for r in results {
print!(
Expand Down Expand Up @@ -735,9 +698,6 @@ fn print_report(results: &[SchemeResult], n_base: usize) {
RESET
);
}

// ── Entry point ───────────────────────────────────────────────────────────────

pub fn run(n_objects: usize) -> Result<()> {
let schemes = [Scheme::First2, Scheme::First3, Scheme::First2Next2];

Expand Down Expand Up @@ -774,7 +734,6 @@ pub fn run(n_objects: usize) -> Result<()> {
std::fs::create_dir_all(&tmp_path).context("failed to create temp dir")?;
println!("{}repos in: {}{}{}", DIM, RESET, tmp_path.display(), RESET);

// ── Spawn one thread per scheme ───────────────────────────────────────────
println!(
"\n{} {:<20} {:<12} {:<14} {:<14} {:<12} {:<10}{}",
DIM, "scheme", "base build", "write batch", "write seq", "read 1k", "diff", RESET
Expand Down Expand Up @@ -831,7 +790,6 @@ pub fn run(n_objects: usize) -> Result<()> {
Scheme::First2Next2 => 2,
});

// ── Print per-scheme logs ─────────────────────────────────────────────────
// Move cursor up past the "running…" lines we printed earlier, then
// overwrite with actual results. Fall back to plain sequential output if
// the terminal doesn't support ANSI cursor movement.
Expand Down Expand Up @@ -876,7 +834,6 @@ pub fn run(n_objects: usize) -> Result<()> {
RESET
);

// ── Verbose per-scheme logs ───────────────────────────────────────────────
for r in &results {
println!("\n{}── {} ──{}", DIM, r.scheme.name(), RESET);
for line in &r.log {
Expand Down
24 changes: 0 additions & 24 deletions src/commands/bench/history_walker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ use std::io::Write;
use std::path::PathBuf;
use std::time::Instant;

// ── ANSI colours (same palette as fanout_bench) ───────────────────────────────
const RESET: &str = "\x1b[0m";
const BOLD: &str = "\x1b[1m";
const DIM: &str = "\x1b[2m";
Expand All @@ -51,12 +50,8 @@ const GREEN: &str = "\x1b[32m";
const MAGENTA: &str = "\x1b[35m";
const RED: &str = "\x1b[31m";

// ── Thresholds (match the spec) ───────────────────────────────────────────────
const PRUNE_THRESHOLD: usize = 5_000;
const PRUNE_KEEP: usize = 500;

// ── Deterministic PRNG (xor-shift-64, same as fanout_bench) ──────────────────

fn xorshift(state: &mut u64) -> u64 {
let mut x = *state;
x ^= x << 13;
Expand Down Expand Up @@ -96,9 +91,6 @@ fn sample_change_count(rng: &mut u64) -> usize {
let count = (200.0 * u.powf(2.5)).ceil() as usize;
count.clamp(1, 200)
}

// ── Tree helpers (mirrors fanout_bench / serialize.rs) ───────────────────────

#[derive(Default)]
struct Dir {
files: BTreeMap<String, Vec<u8>>,
Expand Down Expand Up @@ -254,9 +246,6 @@ fn write_commit(
let parent_refs: Vec<&git2::Commit> = parents.iter().collect();
Ok(repo.commit(None, &sig, &sig, msg, &tree, &parent_refs)?)
}

// ── Generation phase ──────────────────────────────────────────────────────────

struct GenerationStats {
n_normal_commits: usize,
n_prune_commits: usize,
Expand Down Expand Up @@ -435,9 +424,6 @@ fn generate_history(repo: &Repository, n_commits: usize, rng: &mut u64) -> Resul
elapsed_secs: elapsed,
})
}

// ── Walk phase ────────────────────────────────────────────────────────────────

struct WalkStats {
commits_visited: usize,
shas_recovered: usize,
Expand Down Expand Up @@ -520,19 +506,13 @@ fn walk_history(repo: &Repository, tip_oid: Oid) -> Result<WalkStats> {
elapsed_secs: elapsed,
})
}

// ── Report ────────────────────────────────────────────────────────────────────

fn fmt_ms(secs: f64) -> String {
format!("{:.1} ms", secs * 1000.0)
}

fn fmt_us(secs: f64) -> String {
format!("{:.2} µs", secs * 1_000_000.0)
}

// ── Entry point ───────────────────────────────────────────────────────────────

pub fn run(n_commits: usize) -> Result<()> {
println!(
"\n{}gmeta history-walker benchmark{} — {}{} commits to generate{}",
Expand Down Expand Up @@ -572,7 +552,6 @@ pub fn run(n_commits: usize) -> Result<()> {
RESET
);

// ── Generation ────────────────────────────────────────────────────────────
println!("\n{}generating {} commits…{}", BOLD, n_commits, RESET);

let mut rng: u64 = 0xdeadbeef_cafebabe;
Expand Down Expand Up @@ -613,7 +592,6 @@ pub fn run(n_commits: usize) -> Result<()> {
RESET
);

// ── Flush mempack → packfile, set refs/meta/local + HEAD ─────────────────
print!("\n{}flushing mempack to packfile…{}", BOLD, RESET);
let _ = std::io::stdout().flush();
let t_pack = Instant::now();
Expand Down Expand Up @@ -649,7 +627,6 @@ pub fn run(n_commits: usize) -> Result<()> {
RESET,
);

// ── Walk ──────────────────────────────────────────────────────────────────
print!("\n{}walking history from tip…{}", BOLD, RESET);
let _ = std::io::stdout().flush();

Expand Down Expand Up @@ -695,7 +672,6 @@ pub fn run(n_commits: usize) -> Result<()> {
};
println!(" {}correctness{} {}", DIM, RESET, match_str);

// ── Timing summary ────────────────────────────────────────────────────────
println!("\n{}timing summary{}", BOLD, RESET);
let gen_per_commit = gen.elapsed_secs / gen.commit_chain.len() as f64;
let walk_per_commit = walk.elapsed_secs / walk.commits_visited.max(1) as f64;
Expand Down
Loading
Loading