OXYGENHUB
# b576d05cf862 spectra / tests / bench.rs
2.8 KiB · Rust · last changed README quick start, a systemd user unit, and the spec §24 measurements; #13 ready for Andy 2 days ago source blame history raw
1
//! The targets of spec §24, measured: `brief` and `say` with a thousand
2
//! messages in the ledger, and how soon `wait` wakes after a mention. Run
3
//! in release, by hand:
4
//!
5
//! `cargo test --release --test bench -- --ignored --nocapture`
6
7
mod common;
8
9
use common::{add_agent, setup, Serving};
10
use serde_json::json;
11
use spectra_mcp::client::{rpc_result, Client};
12
use std::time::{Duration, Instant};
13
14
async fn call(c: &Client, name: &str, args: serde_json::Value) -> serde_json::Value {
15
    let req = json!({ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": name, "arguments": args } });
16
    rpc_result(&c.mcp("2025-11-25", &req).await.unwrap()).unwrap()
17
}
18
19
fn median(mut v: Vec<Duration>) -> Duration {
20
    v.sort();
21
    v[v.len() / 2]
22
}
23
24
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
25
#[ignore]
26
async fn spec_24_targets() {
27
    let dir = setup();
28
    let d = dir.path();
29
    let a = add_agent(d, "bench-a", &[]);
30
    let b = add_agent(d, "bench-b", &[]);
31
    let srv = Serving::start(d);
32
    let (ca, cb) = (Client::new(&srv.socket, Some(a)), Client::new(&srv.socket, Some(b)));
33
    for i in 0..1_000 {
34
        call(&ca, "say", json!({ "body": format!("message {i} about the pin bump"), "channel": "general" })).await;
35
    }
36
    let mut brief = Vec::new();
37
    let mut say = Vec::new();
38
    for i in 0..50 {
39
        let t = Instant::now();
40
        call(&ca, "brief", json!({})).await;
41
        brief.push(t.elapsed());
42
        let t = Instant::now();
43
        call(&ca, "say", json!({ "body": format!("timed {i}") })).await;
44
        say.push(t.elapsed());
45
    }
46
    let mut wake = Vec::new();
47
    for i in 0..10 {
48
        let w = tokio::spawn({
49
            let cb = Client::new(&srv.socket, Some(spectra_core::keys::KeyPair::load_home(&d.join("agents/bench-b")).unwrap()));
50
            async move {
51
                call(&cb, "wait", json!({ "timeout_s": 20 })).await;
52
                Instant::now()
53
            }
54
        });
55
        tokio::time::sleep(Duration::from_millis(200)).await;
56
        let sent = Instant::now();
57
        call(&ca, "say", json!({ "body": format!("@bench-b wake {i}"), "channel": "general" })).await;
58
        wake.push(w.await.unwrap().saturating_duration_since(sent));
59
        call(&cb, "ack", json!({ "ids": [] })).await;
60
        let inbox = call(&cb, "inbox", json!({})).await;
61
        let ids: Vec<serde_json::Value> =
62
            inbox["result"]["structuredContent"]["items"].as_array().unwrap().iter().map(|i| i["id"].clone()).collect();
63
        call(&cb, "ack", json!({ "ids": ids })).await;
64
    }
65
    println!("spec §24 with 1,000 messages, round trip over the socket including signing:");
66
    println!("  brief  median {:?}", median(brief));
67
    println!("  say    median {:?}", median(say));
68
    println!("  wait   wakes {:?} after the mention is sent (median)", median(wake));
69
    srv.stop();
70
}