~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
109 lines · 4.0 KB Raw History
//! What a repository's pulls and issues cost a page: read from the index
//! and assembled on every ask, as each page did, against what the index
//! keeps of them, and what writes elsewhere and to it do to that.
//!
//!   cargo run --release -p knotless-serve --example forge -- <index.db> <repo at-uri>
//!
//! The index is written to, so give it a copy: prod's, say, for a busy
//! repository's numbers.

use knotless::records::{RepoRecord, nsid};
use knotless_serve::index::Index;
use serde_json::json;
use std::path::PathBuf;
use std::time::{Duration, Instant};

/// Runs `f` until a second has passed, at least ten times; the median and
/// the slowest one in a hundred.
fn time<T>(mut f: impl FnMut() -> T) -> (Duration, Duration) {
    let mut runs = Vec::new();
    let start = Instant::now();
    while runs.len() < 10 || start.elapsed() < Duration::from_secs(1) {
        let t = Instant::now();
        std::hint::black_box(f());
        runs.push(t.elapsed());
    }
    runs.sort();
    (runs[runs.len() / 2], runs[runs.len() * 99 / 100])
}

fn ms(d: Duration) -> String {
    format!("{:.3}", d.as_secs_f64() * 1000.0)
}

fn row(what: &str, (median, slow): (Duration, Duration)) {
    println!("{what:<44} {:>9} {:>9}", ms(median), ms(slow));
}

fn main() {
    let args: Vec<String> = std::env::args().skip(1).collect();
    let [path, uri] = &args[..] else {
        eprintln!("usage: forge <index.db> <repo at-uri>");
        std::process::exit(2);
    };
    let index = Index::open(&PathBuf::from(path)).expect("an index");
    let value = index.repo(uri).expect("readable").expect("the repository");
    let record: RepoRecord = serde_json::from_value(value).expect("a repository record");
    let did = uri.trim_start_matches("at://").split('/').next().unwrap();
    let key = record.key.clone();
    let entries = index.forge(did, &key).unwrap();
    let items = knotless::forge::assemble(&record, did, &entries);
    println!(
        "{uri}: {} records, {} pulls and issues\n",
        entries.len(),
        items.len()
    );
    println!("{:<44} {:>9} {:>9}", "ms", "median", "p99");

    let before = time(|| {
        let entries = index.forge(did, &key).unwrap();
        knotless::forge::assemble(&record, did, &entries)
    });
    row("read and assembled, as every ask was", before);
    let kept = time(|| index.assembled(did, &key, &record).unwrap());
    row("kept", kept);

    // The network writing about another repository leaves it kept.
    let mut n = 0;
    let elsewhere = time(|| {
        n += 1;
        let other = json!({"uri": "at://did:plc:other/dev.knotless.repo/x", "key": "x"});
        let said = json!({"repo": other, "subject": "at://did:plc:other/dev.knotless.issue/1",
            "body": "hi", "createdAt": "2026-10-29T00:00:00Z"});
        index
            .put("did:plc:other", nsid::COMMENT, &format!("c{n}"), &said)
            .unwrap();
        index.assembled(did, &key, &record).unwrap()
    });
    row("kept, with a write elsewhere before each", elsewhere);
    let accounts = time(|| {
        n += 1;
        index
            .set_status(&format!("did:plc:gone{n}"), "deactivated")
            .unwrap();
        index.assembled(did, &key, &record).unwrap()
    });
    row("kept, with an account elsewhere deactivated", accounts);

    // A comment on it is read and assembled again.
    let repo = json!({"uri": uri, "key": key});
    let on = time(|| {
        n += 1;
        let said = json!({"repo": repo, "subject": items[0].uri, "body": "hi",
            "createdAt": "2026-10-29T00:00:00Z"});
        index
            .put("did:plc:bench", nsid::COMMENT, &format!("c{n}"), &said)
            .unwrap();
        index.assembled(did, &key, &record).unwrap()
    });
    row("with a comment on it before each", on);

    // What a pull's files page asked before, each assembling them anew:
    // getRepo once, getThread three times, getPullDiff twice.
    let page = |one: Duration| one * 6;
    println!(
        "\na pull's files page: {} ms assembling before, {} ms kept",
        ms(page(before.0)),
        ms(page(kept.0))
    );
}