codesynapse-core 0.1.0

Core graph extraction and analysis engine for codesynapse — AST parsing, semantic embeddings, BM25 index
Documentation
use criterion::{black_box, criterion_group, criterion_main, Criterion};

use codesynapse_core::build::GraphBuilder;
use codesynapse_core::dedup::Deduplicator;
use codesynapse_core::detect::Detector;
use codesynapse_core::export::Exporter;
use codesynapse_core::extract::Extractor;
use codesynapse_core::graph::MemoryGraphStore;
use codesynapse_core::types::{Edge, Node};

fn make_node(i: usize) -> Node {
    Node {
        id: format!("node_{i}"),
        label: format!("function_{i}"),
        file_type: "Code".to_string(),
        source_file: format!("src/file_{}.rs", i % 100),
        source_location: Some(format!("L{i}")),
        community: Some(i % 10),
        rationale: None,
        docstring: None,
        metadata: Default::default(),
    }
}

fn make_edge(i: usize, node_count: usize) -> Edge {
    Edge {
        source: format!("node_{}", i % node_count),
        target: format!("node_{}", (i + 1) % node_count),
        relation: "calls".to_string(),
        confidence: "INFERRED".to_string(),
        source_file: None,
        weight: 1.0,
        context: None,
    }
}

fn bench_detect_1k(c: &mut Criterion) {
    use std::fs;
    let dir = tempfile::tempdir().unwrap();
    for i in 0..1_000 {
        let path = dir.path().join(format!("file_{i}.py"));
        fs::write(&path, format!("def fn_{i}(): pass\n")).unwrap();
    }
    let det = Detector::new(dir.path());
    c.bench_function("detect_1k_files", |b| {
        b.iter(|| black_box(det.discover(dir.path()).unwrap()))
    });
}

fn bench_extract_100(c: &mut Criterion) {
    use std::fs;
    let dir = tempfile::tempdir().unwrap();
    let mut paths = Vec::new();
    for i in 0..100 {
        let path = dir.path().join(format!("module_{i}.py"));
        let src =
            format!("import os\ndef func_{i}(x, y):\n    return x + y\nclass Cls_{i}:\n    pass\n");
        fs::write(&path, &src).unwrap();
        paths.push((path, src.into_bytes()));
    }
    let ext = Extractor::new();
    c.bench_function("extract_100_files", |b| {
        b.iter(|| {
            let mut frags = Vec::new();
            for (p, src) in &paths {
                if let Ok(f) = ext.extract_file(p, src) {
                    frags.push(f);
                }
            }
            black_box(frags)
        })
    });
}

fn bench_build_10k(c: &mut Criterion) {
    let nodes: Vec<Node> = (0..10_000).map(make_node).collect();
    let edges: Vec<Edge> = (0..15_000).map(|i| make_edge(i, 10_000)).collect();
    c.bench_function("build_graph_10k_nodes", |b| {
        b.iter(|| {
            let store = Box::new(MemoryGraphStore::new());
            let builder = GraphBuilder::new(store);
            builder.add_nodes(nodes.clone()).unwrap();
            builder.add_edges(edges.clone()).unwrap();
            black_box(builder)
        })
    });
}

fn bench_dedup_50k(c: &mut Criterion) {
    let nodes: Vec<Node> = (0..1_000).map(make_node).collect();
    let edges: Vec<Edge> = (0..50_000).map(|i| make_edge(i, 1_000)).collect();
    let dedup = Deduplicator::new(Deduplicator::default_threshold());
    c.bench_function("dedup_50k_edges", |b| {
        b.iter(|| black_box(dedup.deduplicate(nodes.clone(), edges.clone()).unwrap()))
    });
}

fn bench_export_json_10k(c: &mut Criterion) {
    let nodes: Vec<Node> = (0..10_000).map(make_node).collect();
    let edges: Vec<Edge> = (0..12_000).map(|i| make_edge(i, 10_000)).collect();
    let exporter = Exporter;
    c.bench_function("export_json_10k_nodes", |b| {
        b.iter(|| black_box(exporter.to_json(&nodes, &edges, None).unwrap()))
    });
}

criterion_group!(
    extraction_benches,
    bench_detect_1k,
    bench_extract_100,
    bench_build_10k,
    bench_dedup_50k,
    bench_export_json_10k,
);
criterion_main!(extraction_benches);