use std::{alloc::System, hint::black_box, sync::Arc, time::Instant};
use arrow::{
array::{ArrayRef, UInt64Array},
datatypes::{DataType, Field, Schema},
record_batch::RecordBatch,
};
use rxgraph::Graph;
use stats_alloc::{INSTRUMENTED_SYSTEM, Region, StatsAlloc};
#[global_allocator]
static GLOBAL: &StatsAlloc<System> = &INSTRUMENTED_SYSTEM;
const NODES: u64 = 5_000_000;
const REACHABLE_CHAIN: u64 = 5_000;
fn batch(fields: Vec<Field>, columns: Vec<ArrayRef>) -> RecordBatch {
RecordBatch::try_new(Arc::new(Schema::new(fields)), columns).unwrap()
}
fn tables() -> (RecordBatch, RecordBatch) {
let node_ids: Vec<u64> = (0..NODES).collect();
let nodes = batch(
vec![Field::new("id", DataType::UInt64, false)],
vec![Arc::new(UInt64Array::from(node_ids)) as ArrayRef],
);
let edge_count = REACHABLE_CHAIN;
let edge_ids: Vec<u64> = (0..edge_count).collect();
let srcs: Vec<u64> = (0..edge_count).collect();
let dests: Vec<u64> = (1..=edge_count).collect();
let edges = batch(
vec![
Field::new("id", DataType::UInt64, false),
Field::new("src", DataType::UInt64, false),
Field::new("dest", DataType::UInt64, false),
],
vec![
Arc::new(UInt64Array::from(edge_ids)) as ArrayRef,
Arc::new(UInt64Array::from(srcs)),
Arc::new(UInt64Array::from(dests)),
],
);
(nodes, edges)
}
fn mib(bytes: isize) -> f64 {
bytes as f64 / (1024.0 * 1024.0)
}
fn measure<T>(label: &str, f: impl FnOnce() -> T) -> T {
let region = Region::new(GLOBAL);
let started = Instant::now();
let value = f();
let stats = region.change();
let elapsed = started.elapsed();
let retained = stats.bytes_allocated as isize - stats.bytes_deallocated as isize;
eprintln!(
"{label:<28} retained={:>9.2} MiB churn={:>8.2} MiB in {:<8} allocs (freed={:.2} MiB) {elapsed:?}",
mib(retained),
mib(stats.bytes_allocated as isize),
stats.allocations,
mib(stats.bytes_deallocated as isize),
);
value
}
fn main() {
eprintln!("memory profile: nodes={NODES} reachable_chain={REACHABLE_CHAIN}\n");
let (nodes, edges) = tables();
let graph = measure("construct", || Graph::new(nodes, edges).unwrap());
measure("bfs_from_source", || {
black_box(graph.bfs_u64(0, None).unwrap());
});
measure("in_degrees (builds rev CSR)", || {
black_box(graph.in_degrees());
});
measure("weakly_connected (rev cached)", || {
black_box(graph.weakly_connected_components_u64());
});
black_box(&graph);
}