graph_api_benches/
mutation.rs

1use crate::generators::{GraphSize, generate_random_graph, generate_test_graph};
2
3use criterion::{BenchmarkGroup, Throughput, measurement::WallTime};
4#[cfg(feature = "element-removal")]
5use graph_api_lib::SupportsElementRemoval;
6use graph_api_lib::{Graph, VertexReferenceMut, VertexSearch};
7use graph_api_test::{Edge, PersonMut, Vertex, VertexExt};
8
9/// Run all mutation operation benchmarks
10pub fn run_benchmarks<G: Graph<Vertex = Vertex, Edge = Edge>>(
11    group: &mut BenchmarkGroup<WallTime>,
12    setup: impl Fn() -> G + Clone,
13) {
14    bench_mutation_vertex_update(group, setup.clone());
15    bench_mutation_edge_add(group, setup.clone());
16
17    // Only run removal benchmarks if the feature is enabled and graph supports removal
18    #[cfg(feature = "element-removal")]
19    run_removal_benchmarks(group, setup);
20}
21
22/// Run removal-specific benchmarks
23#[cfg(feature = "element-removal")]
24fn run_removal_benchmarks<G: Graph<Vertex = Vertex, Edge = Edge> + SupportsElementRemoval>(
25    group: &mut BenchmarkGroup<WallTime>,
26    setup: impl Fn() -> G + Clone,
27) {
28    bench_mutation_edge_remove(group, setup.clone());
29}
30
31/// Benchmark updating vertices during traversal
32fn bench_mutation_vertex_update<G: Graph<Vertex = Vertex, Edge = Edge>>(
33    group: &mut BenchmarkGroup<WallTime>,
34    setup: impl Fn() -> G + Clone,
35) {
36    group.throughput(Throughput::Elements(10));
37    group.bench_function("mutation_vertex_update", |b| {
38        b.iter_batched(
39            || {
40                // Setup: Create graph with random data
41                let mut graph = setup();
42                generate_random_graph(&mut graph, GraphSize::Small, 42);
43                graph
44            },
45            |mut graph| {
46                // Update age of first 10 Person vertices by incrementing it
47                graph
48                    .walk_mut()
49                    .vertices(VertexSearch::scan())
50                    .filter_person()
51                    .take(10)
52                    .mutate(|graph, vertex_id, _context| {
53                        let mut vertex = graph.vertex_mut(vertex_id).expect("vertex");
54                        let mut person = vertex.project_mut::<PersonMut<_, _>>().expect("person");
55                        person.set_age(100)
56                    })
57            },
58            criterion::BatchSize::SmallInput,
59        )
60    });
61}
62
63/// Benchmark adding edges during traversal
64fn bench_mutation_edge_add<G: Graph<Vertex = Vertex, Edge = Edge>>(
65    group: &mut BenchmarkGroup<WallTime>,
66    setup: impl Fn() -> G + Clone,
67) {
68    group.throughput(Throughput::Elements(1));
69    group.bench_function("mutation_edge_add", |b| {
70        b.iter_batched(
71            || {
72                // Setup: Create graph with test data
73                let mut graph = setup();
74                let refs = generate_test_graph(&mut graph);
75                (graph, refs.julia, refs.rust)
76            },
77            |(mut graph, source_id, target_id)| {
78                // Add an edge during traversal
79                graph
80                    .walk_mut()
81                    .vertices_by_id(vec![source_id])
82                    .mutate(|graph, _, _| {
83                        graph.add_edge(source_id, target_id, Edge::Created);
84                    })
85            },
86            criterion::BatchSize::SmallInput,
87        )
88    });
89}
90
91/// Benchmark removing edges during traversal
92#[cfg(feature = "element-removal")]
93fn bench_mutation_edge_remove<G: Graph<Vertex = Vertex, Edge = Edge> + SupportsElementRemoval>(
94    group: &mut BenchmarkGroup<WallTime>,
95    setup: impl Fn() -> G + Clone,
96) {
97    group.throughput(Throughput::Elements(1));
98    group.bench_function("mutation_edge_remove", |b| {
99        b.iter_batched(
100            || {
101                // Setup: Create graph with test data
102                let mut graph = setup();
103                let _refs = generate_test_graph(&mut graph);
104                graph
105            },
106            |mut graph| {
107                // Find and remove the first outgoing edge from Bryn
108                let count = graph
109                    .walk_mut()
110                    .vertices(VertexSearch::scan())
111                    .edges(EdgeSearch::scan().outgoing())
112                    .take(1)
113                    .mutate(|graph, edge_id, _| {
114                        graph.remove_edge(edge_id);
115                    });
116                count
117            },
118            criterion::BatchSize::SmallInput,
119        )
120    });
121}