use macrame::graph::{EdgeRef, NodeData, Subgraph};
const TS: &str = "2026-01-01T00:00:00.000000Z";
const OPEN: &str = "9999-12-31T23:59:59.999999Z";
fn edge_entry_bytes(id_len: usize, edge_type_len: usize) -> usize {
id_len + edge_type_len + TS.len() + OPEN.len() + std::mem::size_of::<EdgeRef>()
}
const INTERNED_EDGE_ENTRY_BYTES: usize = 24;
fn main() {
println!("Subgraph byte accounting, by the loader's own formula.\n");
println!("size_of::<EdgeRef>() = {}", std::mem::size_of::<EdgeRef>());
println!(
"size_of::<NodeData>() = {}",
std::mem::size_of::<NodeData>()
);
println!(
"timestamp width = {} bytes, two per entry\n",
TS.len()
);
println!(
"{:>10} {:>12} {:>13} {:>14} {:>12} {:>10}",
"id len", "B/edge now", "B/edge intern", "edges/MiB now", "intern", "ratio"
);
for id_len in [8usize, 26, 64] {
let now = 2 * edge_entry_bytes(id_len, "LINKS".len());
let interned = 2 * INTERNED_EDGE_ENTRY_BYTES;
let mib = 1usize << 20;
println!(
"{:>10} {:>12} {:>13} {:>14} {:>12} {:>9.1}x",
id_len,
now,
interned,
mib / now,
mib / interned,
now as f64 / interned as f64
);
}
println!("\nNode share of the budget, at a fixed 8-byte id and 20 edges/node:");
println!(
"{:>14} {:>14} {:>14} {:>16}",
"content bytes", "node bytes", "edge bytes", "edges' share"
);
for content in [0usize, 200, 2_000, 20_000] {
let mut g = Subgraph::default();
let n = 200usize;
for i in 0..n {
g.nodes.insert(
format!("c{i:07}"),
NodeData {
title: "A title".to_string(),
content: "x".repeat(content),
embedding_model: None,
valid_from: TS.to_string(),
valid_to: OPEN.to_string(),
},
);
}
for i in 0..n {
for k in 1..=20usize {
let source = format!("c{i:07}");
let target = format!("c{:07}", (i + k) % n);
let fwd = EdgeRef {
node: target.clone(),
edge_type: "LINKS".to_string(),
weight: 1.0,
valid_from: TS.to_string(),
valid_to: OPEN.to_string(),
};
let mut back = fwd.clone();
back.node = source.clone();
g.out_adj.entry(source).or_default().push(fwd);
g.in_adj.entry(target).or_default().push(back);
}
}
let total = g.estimated_bytes();
let edge_bytes = 2 * n * 20 * edge_entry_bytes(8, 5);
let node_bytes = total.saturating_sub(edge_bytes);
println!(
"{:>14} {:>14} {:>14} {:>15.0}%",
content,
node_bytes,
edge_bytes,
100.0 * edge_bytes as f64 / total as f64
);
}
}