use graph_d::Graph;
use serde_json::json;
use std::collections::HashMap;
use std::time::Instant;
const MIN_NODE_CREATION_RATE: f64 = 100_000.0;
const MIN_RELATIONSHIP_CREATION_RATE: f64 = 50_000.0;
const MIN_QUERY_THROUGHPUT: f64 = 10_000.0;
#[test]
fn test_node_creation_performance() {
let mut graph = Graph::new().unwrap();
let iterations = 10_000;
let start = Instant::now();
for i in 0..iterations {
let mut props = HashMap::new();
props.insert("id".to_string(), json!(i));
props.insert("name".to_string(), json!(format!("node_{}", i)));
graph.create_node(props).unwrap();
}
let elapsed = start.elapsed();
let rate = iterations as f64 / elapsed.as_secs_f64();
println!(
"Node creation rate: {:.0} nodes/sec (minimum: {:.0})",
rate, MIN_NODE_CREATION_RATE
);
assert!(
rate >= MIN_NODE_CREATION_RATE,
"Node creation rate {:.0}/sec is below minimum threshold {:.0}/sec. \
This indicates a performance regression. Constraint B2 requires 140K+/sec.",
rate,
MIN_NODE_CREATION_RATE
);
}
#[test]
fn test_relationship_creation_performance() {
let mut graph = Graph::new().unwrap();
let mut node_ids = Vec::new();
for i in 0..1000 {
let mut props = HashMap::new();
props.insert("id".to_string(), json!(i));
let id = graph.create_node(props).unwrap();
node_ids.push(id);
}
let iterations = 5_000;
let start = Instant::now();
for i in 0..iterations {
let from = node_ids[i % node_ids.len()];
let to = node_ids[(i + 1) % node_ids.len()];
let mut props = HashMap::new();
props.insert("weight".to_string(), json!(i));
graph
.create_relationship(from, to, "CONNECTS".to_string(), props)
.unwrap();
}
let elapsed = start.elapsed();
let rate = iterations as f64 / elapsed.as_secs_f64();
println!(
"Relationship creation rate: {:.0} rels/sec (minimum: {:.0})",
rate, MIN_RELATIONSHIP_CREATION_RATE
);
assert!(
rate >= MIN_RELATIONSHIP_CREATION_RATE,
"Relationship creation rate {:.0}/sec is below minimum threshold {:.0}/sec",
rate,
MIN_RELATIONSHIP_CREATION_RATE
);
}
#[test]
fn test_adjacency_lookup_performance() {
let mut graph = Graph::new().unwrap();
let mut node_ids = Vec::new();
for i in 0..1000 {
let mut props = HashMap::new();
props.insert("id".to_string(), json!(i));
let id = graph.create_node(props).unwrap();
node_ids.push(id);
}
for i in 0..999 {
let props = HashMap::new();
graph
.create_relationship(node_ids[i], node_ids[i + 1], "NEXT".to_string(), props)
.unwrap();
}
let iterations = 10_000;
let start = Instant::now();
for i in 0..iterations {
let node_id = node_ids[i % node_ids.len()];
let _ = graph.get_node(node_id);
}
let elapsed = start.elapsed();
let rate = iterations as f64 / elapsed.as_secs_f64();
println!(
"Node lookup rate: {:.0} lookups/sec (minimum: {:.0})",
rate, MIN_QUERY_THROUGHPUT
);
assert!(
rate >= MIN_QUERY_THROUGHPUT,
"Node lookup rate {:.0}/sec is below minimum threshold {:.0}/sec. \
Constraint B1 requires O(1) adjacency lookups.",
rate,
MIN_QUERY_THROUGHPUT
);
}
#[test]
fn test_performance_scaling() {
let sizes = [1000, 5000, 10000];
let mut rates = Vec::new();
{
let mut warmup_graph = Graph::new().unwrap();
for i in 0..500 {
let mut props = HashMap::new();
props.insert("id".to_string(), json!(i));
warmup_graph.create_node(props).unwrap();
}
}
for &size in &sizes {
let mut graph = Graph::new().unwrap();
let start = Instant::now();
for i in 0..size {
let mut props = HashMap::new();
props.insert("id".to_string(), json!(i));
graph.create_node(props).unwrap();
}
let elapsed = start.elapsed();
let rate = size as f64 / elapsed.as_secs_f64();
rates.push(rate);
println!("Size {}: {:.0} nodes/sec", size, rate);
}
let degradation = rates[2] / rates[0];
println!("Performance ratio (10000 vs 1000): {:.2}", degradation);
assert!(
degradation > 0.3,
"Performance degrades too much at scale: {:.1}% of baseline. \
This may indicate a performance regression.",
degradation * 100.0
);
}