Skip to main content

bench_many_sessions/
bench_many_sessions.rs

1//! Measure memory retained by many live sessions sharing one compilation.
2//!
3//! Run in a fresh process under `/usr/bin/time -l` on macOS (or `-v` on
4//! Linux). The caller alternates release binaries and repeats samples.
5
6use shifty_engine::{CompiledShapes, FindingOptions, SessionData, SessionOptions};
7use shifty_parse::{Loaded, RdfFormat};
8use std::env;
9use std::hint::black_box;
10use std::path::Path;
11use std::process::Command;
12use std::time::Instant;
13
14fn load(path: &str) -> Loaded {
15    Loaded::from_path(Path::new(path), RdfFormat::Turtle, None).expect("valid Turtle input")
16}
17
18fn rss_kib() -> Option<usize> {
19    let pid = std::process::id().to_string();
20    let output = Command::new("ps")
21        .args(["-o", "rss=", "-p", &pid])
22        .output()
23        .ok()?;
24    String::from_utf8(output.stdout).ok()?.trim().parse().ok()
25}
26
27fn main() {
28    let args: Vec<_> = env::args().skip(1).collect();
29    assert!(
30        args.len() == 3 || (args.len() == 4 && args[3] == "--infer"),
31        "usage: bench_many_sessions SHAPES DATA COUNT [--infer]"
32    );
33    let count: usize = args[2].parse().expect("COUNT must be an integer");
34    assert!(count > 0, "COUNT must be positive");
35    let options = SessionOptions {
36        inference: args.len() == 4,
37        ..SessionOptions::default()
38    };
39    let findings = FindingOptions::default();
40
41    let started = Instant::now();
42    let compiled = CompiledShapes::compile(load(&args[0])).expect("compilable shapes");
43    let compile_ms = started.elapsed().as_secs_f64() * 1000.0;
44    let data = load(&args[1]).graph;
45    let compiled_rss_kib = rss_kib();
46
47    let mut sessions = Vec::with_capacity(count);
48    let started = Instant::now();
49    let mut first_rss_kib = None;
50    for index in 0..count {
51        let session = compiled
52            .session(SessionData::Separate(data.clone()), options)
53            .expect("session");
54        black_box(session.validate(&findings));
55        sessions.push(session);
56        if index == 0 {
57            first_rss_kib = rss_kib();
58        }
59    }
60    let sessions_ms = started.elapsed().as_secs_f64() * 1000.0;
61    let final_rss_kib = rss_kib();
62    black_box(&sessions);
63    println!(
64        "shapes={},data={},count={count},infer={},compile_ms={compile_ms:.2},sessions_ms={sessions_ms:.2},compiled_rss_kib={compiled_rss_kib:?},first_rss_kib={first_rss_kib:?},final_rss_kib={final_rss_kib:?}",
65        args[0], args[1], options.inference,
66    );
67}