graph_api_benches/
mutation.rs

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