graph_api_benches/index/edge_label/
mod.rs

1use criterion::{BenchmarkGroup, measurement::WallTime};
2use graph_api_derive::{EdgeExt, VertexExt};
3use graph_api_lib::Graph;
4#[cfg(feature = "element-removal")]
5use graph_api_lib::SupportsElementRemoval;
6
7use std::fmt::Debug;
8use uuid::Uuid;
9
10// Define a model with edge label indexes
11#[derive(Debug, Clone, VertexExt)]
12pub enum Vertex {
13    Person {
14        name: String,
15        age: u64,
16        unique_id: Uuid,
17        username: String,
18        biography: String,
19    },
20    Project {
21        name: String,
22    },
23    Rust,
24}
25
26#[derive(Debug, Clone, EdgeExt)]
27pub enum Edge {
28    Knows { since: i32 },
29    Created,
30    Language { name: String },
31}
32
33// Generate test data with the EdgeLabelVertex and EdgeLabelEdge models
34pub fn populate_test_data<G>(graph: &mut G) -> (Vec<G::VertexId>, Vec<G::EdgeId>)
35where
36    G: Graph<Vertex = Vertex, Edge = Edge>,
37{
38    let mut person_ids = vec![];
39    let mut edge_ids = vec![];
40
41    // Create person vertices
42    for i in 0..20 {
43        let id = graph.add_vertex(Vertex::Person {
44            name: format!("Person{}", i),
45            age: 25 + (i % 50) as u64,
46            unique_id: Uuid::new_v4(),
47            username: format!("user{}", i),
48            biography: format!("Bio for person {}", i),
49        });
50        person_ids.push(id);
51    }
52
53    // Create edges of different types
54    for i in 0..19 {
55        // Create "knows" edges
56        if i % 3 == 0 {
57            let edge_id = graph.add_edge(
58                person_ids[i],
59                person_ids[i + 1],
60                Edge::Knows {
61                    since: 2020 + (i as i32),
62                },
63            );
64            edge_ids.push(edge_id);
65        }
66    }
67
68    // Add a project and created edges
69    let project = graph.add_vertex(Vertex::Project {
70        name: "TestProject".to_string(),
71    });
72
73    for id in person_ids.iter().take(5) {
74        let edge_id = graph.add_edge(*id, project, Edge::Created);
75        edge_ids.push(edge_id);
76    }
77
78    // Add rust and language edges
79    let rust = graph.add_vertex(Vertex::Rust);
80
81    let edge_id = graph.add_edge(
82        project,
83        rust,
84        Edge::Language {
85            name: "Rust".to_string(),
86        },
87    );
88    edge_ids.push(edge_id);
89
90    (person_ids, edge_ids)
91}
92
93// Individual benchmark functions
94
95#[cfg(feature = "edge-label-index")]
96pub fn bench_lookup<G>(group: &mut BenchmarkGroup<WallTime>, setup: impl Fn() -> G + Clone)
97where
98    G: Graph<Vertex = Vertex, Edge = Edge> + graph_api_lib::SupportsEdgeLabelIndex,
99{
100    // Benchmark edge label index lookup for "knows" edges
101    group.throughput(criterion::Throughput::Elements(1));
102    group.bench_function("edge_label_knows_lookup", |b| {
103        // Setup: Create graph with test data
104        let mut graph = setup();
105        populate_test_data(&mut graph);
106
107        b.iter(|| {
108            // Query edges with "knows" label
109            graph
110                .walk()
111                .vertices(graph_api_lib::VertexSearch::scan())
112                .take(5)
113                .edges(Edge::knows())
114                .collect::<Vec<_>>()
115        })
116    });
117}
118
119#[cfg(not(feature = "edge-label-index"))]
120pub fn bench_lookup<G>(_group: &mut BenchmarkGroup<WallTime>, _setup: impl Fn() -> G + Clone)
121where
122    G: Graph<Vertex = Vertex, Edge = Edge>,
123{
124    // No-op when feature is disabled
125}
126
127#[cfg(feature = "edge-label-index")]
128pub fn bench_insertion<G>(group: &mut BenchmarkGroup<WallTime>, setup: impl Fn() -> G + Clone)
129where
130    G: Graph<Vertex = Vertex, Edge = Edge> + graph_api_lib::SupportsEdgeLabelIndex,
131{
132    // Benchmark insertion with edge label index
133    group.bench_function("edge_label_insertion", |b| {
134        // Setup: Create graph with minimal data for adding edges
135        let mut graph = setup();
136        let (person_ids, _) = populate_test_data(&mut graph);
137        let src = person_ids[0];
138        let dst = person_ids[1];
139
140        b.iter(|| graph.add_edge(src, dst, Edge::Knows { since: 2023 }))
141    });
142}
143
144#[cfg(not(feature = "edge-label-index"))]
145pub fn bench_insertion<G>(_group: &mut BenchmarkGroup<WallTime>, _setup: impl Fn() -> G + Clone)
146where
147    G: Graph<Vertex = Vertex, Edge = Edge>,
148{
149    // No-op when feature is disabled
150}
151
152#[cfg(all(feature = "edge-label-index", feature = "element-removal"))]
153pub fn bench_removal<G>(group: &mut BenchmarkGroup<WallTime>, setup: impl Fn() -> G + Clone)
154where
155    G: Graph<Vertex = Vertex, Edge = Edge>
156        + graph_api_lib::SupportsEdgeLabelIndex
157        + SupportsElementRemoval,
158{
159    // Benchmark removal with edge label index
160    group.bench_function("edge_label_removal", |b| {
161        // Setup: Create a new graph with an edge for each iteration
162        b.iter_with_setup(
163            || {
164                let mut graph = setup();
165                let (person_ids, _) = populate_test_data(&mut graph);
166                let edge_id =
167                    graph.add_edge(person_ids[0], person_ids[1], Edge::Knows { since: 2020 });
168                (graph, edge_id)
169            },
170            |(mut graph, edge_id)| {
171                graph.remove_edge(edge_id);
172            },
173        )
174    });
175}
176
177#[cfg(not(all(feature = "edge-label-index", feature = "element-removal")))]
178pub fn bench_removal<G>(_group: &mut BenchmarkGroup<WallTime>, _setup: impl Fn() -> G + Clone)
179where
180    G: Graph<Vertex = Vertex, Edge = Edge>,
181{
182    // No-op when features are disabled
183}