graph_api_benches/index/vertex_range/
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;
6use std::fmt::Debug;
7use uuid::Uuid;
8
9// Define a model with ONLY range indexes (no hash or fulltext indexes)
10#[derive(Debug, Clone, VertexExt)]
11pub enum Vertex {
12    Person {
13        name: String,
14        #[index(range)]
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 RangeVertex and RangeEdge models
34pub fn populate_test_data<G>(graph: &mut G)
35where
36    G: Graph<Vertex = Vertex, Edge = Edge>,
37{
38    // Create vertices with a range of ages
39    for i in 0..100 {
40        let age = 20 + i % 60; // Ages from 20 to 79
41        graph.add_vertex(Vertex::Person {
42            name: format!("Person{}", i),
43            age,
44            unique_id: Uuid::new_v4(),
45            username: format!("user{}", i),
46            biography: format!("Bio for person {}", i),
47        });
48    }
49
50    // Add some non-person vertices
51    graph.add_vertex(Vertex::Project {
52        name: "TestProject".to_string(),
53    });
54
55    graph.add_vertex(Vertex::Rust);
56}
57
58// Individual benchmark functions
59#[cfg(feature = "vertex-range-index")]
60pub fn bench_lookup<G>(group: &mut BenchmarkGroup<WallTime>, setup: impl Fn() -> G + Clone)
61where
62    G: Graph<Vertex = Vertex, Edge = Edge> + graph_api_lib::SupportsVertexRangeIndex,
63{
64    // Benchmark range property index lookup
65    group.throughput(criterion::Throughput::Elements(1));
66    group.bench_function("vertex_range_age_lookup", |b| {
67        // Setup: Create graph with test data
68        let mut graph = setup();
69        populate_test_data(&mut graph);
70
71        b.iter(|| {
72            // Query by age range (30..50)
73            let results = graph
74                .walk()
75                .vertices(Vertex::person_by_age_range(30..50))
76                .collect::<Vec<_>>();
77
78            assert!(!results.is_empty());
79            results
80        })
81    });
82}
83
84#[cfg(not(feature = "vertex-range-index"))]
85pub fn bench_lookup<G>(_group: &mut BenchmarkGroup<WallTime>, _setup: impl Fn() -> G + Clone)
86where
87    G: Graph<Vertex = Vertex, Edge = Edge>,
88{
89    // No-op when feature is disabled
90}
91
92#[cfg(feature = "vertex-range-index")]
93pub fn bench_insertion<G>(group: &mut BenchmarkGroup<WallTime>, setup: impl Fn() -> G + Clone)
94where
95    G: Graph<Vertex = Vertex, Edge = Edge> + graph_api_lib::SupportsVertexRangeIndex,
96{
97    // Benchmark insertion with range index
98    group.bench_function("vertex_range_insertion", |b| {
99        let mut graph = setup();
100        let mut age = 25;
101
102        b.iter(|| {
103            age = (age + 1) % 100; // Cycle through ages 25-99
104
105            graph.add_vertex(Vertex::Person {
106                name: format!("Range{}", age),
107                age,
108                unique_id: Uuid::new_v4(),
109                username: format!("range_user{}", age),
110                biography: "Test biography for range index".to_string(),
111            })
112        })
113    });
114}
115
116#[cfg(not(feature = "vertex-range-index"))]
117pub fn bench_insertion<G>(_group: &mut BenchmarkGroup<WallTime>, _setup: impl Fn() -> G + Clone)
118where
119    G: Graph<Vertex = Vertex, Edge = Edge>,
120{
121    // No-op when feature is disabled
122}
123
124#[cfg(all(feature = "vertex-range-index", feature = "element-removal"))]
125pub fn bench_removal<G>(group: &mut BenchmarkGroup<WallTime>, setup: impl Fn() -> G + Clone)
126where
127    G: Graph<Vertex = Vertex, Edge = Edge>
128        + graph_api_lib::SupportsVertexRangeIndex
129        + SupportsElementRemoval,
130{
131    // Benchmark removal with range index
132    group.bench_function("vertex_range_removal", |b| {
133        // Setup: Create a new graph for each iteration
134        b.iter_with_setup(
135            || {
136                let mut graph = setup();
137                let vertex_id = graph.add_vertex(Vertex::Person {
138                    name: "RangeRemoveMe".to_string(),
139                    age: 42,
140                    unique_id: Uuid::new_v4(),
141                    username: "range_remove_user".to_string(),
142                    biography: "To be removed from range index".to_string(),
143                });
144                (graph, vertex_id)
145            },
146            |(mut graph, vertex_id)| {
147                graph.remove_vertex(vertex_id);
148            },
149        )
150    });
151}
152
153#[cfg(not(all(feature = "vertex-range-index", feature = "element-removal")))]
154pub fn bench_removal<G>(_group: &mut BenchmarkGroup<WallTime>, _setup: impl Fn() -> G + Clone)
155where
156    G: Graph<Vertex = Vertex, Edge = Edge>,
157{
158    // No-op when features are disabled
159}