vexra 1.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vexra-1.1.1/Cargo.toml +70 -0
- vexra-1.1.1/PKG-INFO +74 -0
- vexra-1.1.1/README.md +50 -0
- vexra-1.1.1/crates/vexra-core/Cargo.toml +25 -0
- vexra-1.1.1/crates/vexra-core/benches/search_bench.rs +185 -0
- vexra-1.1.1/crates/vexra-core/src/collection.rs +578 -0
- vexra-1.1.1/crates/vexra-core/src/config.rs +273 -0
- vexra-1.1.1/crates/vexra-core/src/db.rs +541 -0
- vexra-1.1.1/crates/vexra-core/src/error.rs +38 -0
- vexra-1.1.1/crates/vexra-core/src/lib.rs +39 -0
- vexra-1.1.1/crates/vexra-index/Cargo.toml +19 -0
- vexra-1.1.1/crates/vexra-index/src/distance.rs +581 -0
- vexra-1.1.1/crates/vexra-index/src/error.rs +22 -0
- vexra-1.1.1/crates/vexra-index/src/flat.rs +195 -0
- vexra-1.1.1/crates/vexra-index/src/hnsw/builder.rs +92 -0
- vexra-1.1.1/crates/vexra-index/src/hnsw/graph.rs +567 -0
- vexra-1.1.1/crates/vexra-index/src/hnsw/mod.rs +93 -0
- vexra-1.1.1/crates/vexra-index/src/hnsw/node.rs +123 -0
- vexra-1.1.1/crates/vexra-index/src/hnsw/search.rs +91 -0
- vexra-1.1.1/crates/vexra-index/src/lib.rs +85 -0
- vexra-1.1.1/crates/vexra-metadata/Cargo.toml +16 -0
- vexra-1.1.1/crates/vexra-metadata/src/error.rs +22 -0
- vexra-1.1.1/crates/vexra-metadata/src/filter.rs +344 -0
- vexra-1.1.1/crates/vexra-metadata/src/lib.rs +13 -0
- vexra-1.1.1/crates/vexra-metadata/src/store.rs +137 -0
- vexra-1.1.1/crates/vexra-storage/Cargo.toml +20 -0
- vexra-1.1.1/crates/vexra-storage/src/encoding.rs +130 -0
- vexra-1.1.1/crates/vexra-storage/src/error.rs +46 -0
- vexra-1.1.1/crates/vexra-storage/src/format.rs +516 -0
- vexra-1.1.1/crates/vexra-storage/src/lib.rs +35 -0
- vexra-1.1.1/crates/vexra-storage/src/page_cache.rs +486 -0
- vexra-1.1.1/crates/vexra-storage/src/wal.rs +504 -0
- vexra-1.1.1/pyproject.toml +36 -0
- vexra-1.1.1/sdk/python/Cargo.lock +431 -0
- vexra-1.1.1/sdk/python/Cargo.toml +25 -0
- vexra-1.1.1/sdk/python/README.md +50 -0
- vexra-1.1.1/sdk/python/src/lib.rs +107 -0
- vexra-1.1.1/vexra/__init__.py +7 -0
vexra-1.1.1/Cargo.toml
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
[workspace]
|
|
2
|
+
resolver = "2"
|
|
3
|
+
members = [
|
|
4
|
+
"crates/vexra-core",
|
|
5
|
+
"crates/vexra-storage",
|
|
6
|
+
"crates/vexra-index",
|
|
7
|
+
"crates/vexra-metadata",
|
|
8
|
+
"crates/vexra-query",
|
|
9
|
+
"crates/vexra-ffi",
|
|
10
|
+
"crates/vexra-cli",
|
|
11
|
+
"crates/vexra-server",
|
|
12
|
+
"crates/vexra-embedding",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[workspace.package]
|
|
16
|
+
version = "1.0.0-rc1"
|
|
17
|
+
edition = "2021"
|
|
18
|
+
license = "MIT"
|
|
19
|
+
repository = "https://github.com/embeddb/embeddb"
|
|
20
|
+
authors = ["EmbedDB Contributors"]
|
|
21
|
+
|
|
22
|
+
[workspace.dependencies]
|
|
23
|
+
# Serialization
|
|
24
|
+
serde = { version = "1", features = ["derive"] }
|
|
25
|
+
serde_json = "1"
|
|
26
|
+
bytemuck = { version = "1", features = ["derive"] }
|
|
27
|
+
|
|
28
|
+
# Error handling
|
|
29
|
+
thiserror = "2"
|
|
30
|
+
|
|
31
|
+
# Logging
|
|
32
|
+
log = "0.4"
|
|
33
|
+
tracing = "0.1"
|
|
34
|
+
|
|
35
|
+
# Concurrency
|
|
36
|
+
parking_lot = "0.12"
|
|
37
|
+
arc-swap = "1"
|
|
38
|
+
|
|
39
|
+
# CLI
|
|
40
|
+
clap = { version = "4", features = ["derive"] }
|
|
41
|
+
|
|
42
|
+
# Storage
|
|
43
|
+
memmap2 = "0.9"
|
|
44
|
+
crc32fast = "1"
|
|
45
|
+
|
|
46
|
+
# Big arrays / SIMD
|
|
47
|
+
rustix = "0.38"
|
|
48
|
+
|
|
49
|
+
# Web server (Phase 2)
|
|
50
|
+
# axum = "0.7"
|
|
51
|
+
# tokio = { version = "1", features = ["full"] }
|
|
52
|
+
# tower-http = { version = "0.5", features = ["cors", "fs"] }
|
|
53
|
+
# rust-embed = "8"
|
|
54
|
+
|
|
55
|
+
# ONNX (Phase 2, feature-gated)
|
|
56
|
+
# ort = "2"
|
|
57
|
+
|
|
58
|
+
# Text search (Phase 3)
|
|
59
|
+
# tantivy = "0.22"
|
|
60
|
+
|
|
61
|
+
[profile.release]
|
|
62
|
+
opt-level = 3
|
|
63
|
+
lto = true
|
|
64
|
+
codegen-units = 1
|
|
65
|
+
strip = true
|
|
66
|
+
|
|
67
|
+
[profile.bench]
|
|
68
|
+
opt-level = 3
|
|
69
|
+
lto = true
|
|
70
|
+
codegen-units = 1
|
vexra-1.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vexra
|
|
3
|
+
Version: 1.1.1
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Intended Audience :: Developers
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Rust
|
|
13
|
+
Classifier: Topic :: Database
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Requires-Dist: pytest>=7 ; extra == 'dev'
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Summary: Vexra Python SDK — embedded vector database
|
|
18
|
+
License: MIT
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
21
|
+
Project-URL: Homepage, https://github.com/Mengxun326/embeddb
|
|
22
|
+
Project-URL: Issues, https://github.com/Mengxun326/embeddb/issues
|
|
23
|
+
|
|
24
|
+
# EmbedDB Python SDK
|
|
25
|
+
|
|
26
|
+
Python bindings for EmbedDB — the embedded vector database.
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install embeddb
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
import embeddb
|
|
38
|
+
|
|
39
|
+
# Open or create a database
|
|
40
|
+
db = embeddb.Database("data.embeddb")
|
|
41
|
+
|
|
42
|
+
# Create a collection
|
|
43
|
+
col = db.create_collection("docs", dimension=384, distance=embeddb.DistanceMetric.COSINE)
|
|
44
|
+
|
|
45
|
+
# Insert vectors
|
|
46
|
+
col.insert({"id": "doc1", "vector": [0.1] * 384, "metadata": {"title": "Hello"}})
|
|
47
|
+
col.insert({"id": "doc2", "vector": [0.2] * 384, "metadata": {"title": "World"}})
|
|
48
|
+
|
|
49
|
+
# Search
|
|
50
|
+
results = col.search(vector=[0.15] * 384, top_k=10)
|
|
51
|
+
for hit in results:
|
|
52
|
+
print(f"{hit.id}: {hit.score:.4f}")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## API
|
|
56
|
+
|
|
57
|
+
### Database
|
|
58
|
+
|
|
59
|
+
- `Database(path)` — Open or create a database
|
|
60
|
+
- `db.create_collection(name, dimension, distance)` — Create a collection
|
|
61
|
+
- `db.get_collection(name)` — Get an existing collection
|
|
62
|
+
- `db.close()` — Close the database
|
|
63
|
+
|
|
64
|
+
### Collection
|
|
65
|
+
|
|
66
|
+
- `col.insert(doc)` — Insert a document `{"id": str, "vector": [float], "metadata": dict}`
|
|
67
|
+
- `col.search(vector, top_k=10)` — Search for nearest neighbors
|
|
68
|
+
|
|
69
|
+
### Distance Metrics
|
|
70
|
+
|
|
71
|
+
- `DistanceMetric.COSINE` — Cosine distance
|
|
72
|
+
- `DistanceMetric.EUCLIDEAN` — Euclidean (L2) distance
|
|
73
|
+
- `DistanceMetric.DOT_PRODUCT` — Dot product similarity
|
|
74
|
+
|
vexra-1.1.1/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# EmbedDB Python SDK
|
|
2
|
+
|
|
3
|
+
Python bindings for EmbedDB — the embedded vector database.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install embeddb
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
import embeddb
|
|
15
|
+
|
|
16
|
+
# Open or create a database
|
|
17
|
+
db = embeddb.Database("data.embeddb")
|
|
18
|
+
|
|
19
|
+
# Create a collection
|
|
20
|
+
col = db.create_collection("docs", dimension=384, distance=embeddb.DistanceMetric.COSINE)
|
|
21
|
+
|
|
22
|
+
# Insert vectors
|
|
23
|
+
col.insert({"id": "doc1", "vector": [0.1] * 384, "metadata": {"title": "Hello"}})
|
|
24
|
+
col.insert({"id": "doc2", "vector": [0.2] * 384, "metadata": {"title": "World"}})
|
|
25
|
+
|
|
26
|
+
# Search
|
|
27
|
+
results = col.search(vector=[0.15] * 384, top_k=10)
|
|
28
|
+
for hit in results:
|
|
29
|
+
print(f"{hit.id}: {hit.score:.4f}")
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## API
|
|
33
|
+
|
|
34
|
+
### Database
|
|
35
|
+
|
|
36
|
+
- `Database(path)` — Open or create a database
|
|
37
|
+
- `db.create_collection(name, dimension, distance)` — Create a collection
|
|
38
|
+
- `db.get_collection(name)` — Get an existing collection
|
|
39
|
+
- `db.close()` — Close the database
|
|
40
|
+
|
|
41
|
+
### Collection
|
|
42
|
+
|
|
43
|
+
- `col.insert(doc)` — Insert a document `{"id": str, "vector": [float], "metadata": dict}`
|
|
44
|
+
- `col.search(vector, top_k=10)` — Search for nearest neighbors
|
|
45
|
+
|
|
46
|
+
### Distance Metrics
|
|
47
|
+
|
|
48
|
+
- `DistanceMetric.COSINE` — Cosine distance
|
|
49
|
+
- `DistanceMetric.EUCLIDEAN` — Euclidean (L2) distance
|
|
50
|
+
- `DistanceMetric.DOT_PRODUCT` — Dot product similarity
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "vexra-core"
|
|
3
|
+
version.workspace = true
|
|
4
|
+
edition.workspace = true
|
|
5
|
+
license.workspace = true
|
|
6
|
+
description = "EmbedDB core: public API, Database and Collection handles"
|
|
7
|
+
|
|
8
|
+
[dependencies]
|
|
9
|
+
vexra-storage = { path = "../vexra-storage" }
|
|
10
|
+
vexra-index = { path = "../vexra-index" }
|
|
11
|
+
vexra-metadata = { path = "../vexra-metadata" }
|
|
12
|
+
serde.workspace = true
|
|
13
|
+
serde_json.workspace = true
|
|
14
|
+
thiserror.workspace = true
|
|
15
|
+
log.workspace = true
|
|
16
|
+
parking_lot.workspace = true
|
|
17
|
+
|
|
18
|
+
[dev-dependencies]
|
|
19
|
+
tempfile = "3"
|
|
20
|
+
rand = "0.8"
|
|
21
|
+
criterion = { version = "0.5", features = ["html_reports"] }
|
|
22
|
+
|
|
23
|
+
[[bench]]
|
|
24
|
+
name = "search_bench"
|
|
25
|
+
harness = false
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
//! EmbedDB benchmarks: Flat vs HNSW insert and search performance.
|
|
2
|
+
//!
|
|
3
|
+
//! Run with: cargo bench
|
|
4
|
+
|
|
5
|
+
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
|
|
6
|
+
use vexra_core::collection::{Collection, IndexType};
|
|
7
|
+
use vexra_core::config::{CollectionConfig, SearchQuery};
|
|
8
|
+
use vexra_core::DistanceMetric;
|
|
9
|
+
use vexra_index::flat::FlatIndex;
|
|
10
|
+
use vexra_index::hnsw::graph::HnswGraph;
|
|
11
|
+
use vexra_index::hnsw::HnswConfig;
|
|
12
|
+
use vexra_index::{SearchResult, VectorIndex};
|
|
13
|
+
use rand::Rng;
|
|
14
|
+
use std::time::Duration;
|
|
15
|
+
|
|
16
|
+
const DIM: usize = 128;
|
|
17
|
+
|
|
18
|
+
/// Generate `n` random normalized vectors of dimension `DIM`.
|
|
19
|
+
fn random_vectors(n: usize) -> Vec<Vec<f32>> {
|
|
20
|
+
let mut rng = rand::thread_rng();
|
|
21
|
+
(0..n)
|
|
22
|
+
.map(|_| (0..DIM).map(|_| rng.gen::<f32>()).collect())
|
|
23
|
+
.collect()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/// Build a random FlatIndex with `n` vectors.
|
|
27
|
+
fn build_flat(n: usize) -> FlatIndex {
|
|
28
|
+
let mut idx = FlatIndex::new(DIM, DistanceMetric::Euclidean);
|
|
29
|
+
for (i, v) in random_vectors(n).into_iter().enumerate() {
|
|
30
|
+
idx.insert(i as u64, &v).unwrap();
|
|
31
|
+
}
|
|
32
|
+
idx
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// Build a random HNSW graph with `n` vectors.
|
|
36
|
+
fn build_hnsw(n: usize) -> HnswGraph {
|
|
37
|
+
let config = HnswConfig::new(16).with_ef_construction(200);
|
|
38
|
+
let mut graph = HnswGraph::new(DIM, DistanceMetric::Euclidean, config);
|
|
39
|
+
for (i, v) in random_vectors(n).into_iter().enumerate() {
|
|
40
|
+
graph.insert(i as u64, &v).unwrap();
|
|
41
|
+
}
|
|
42
|
+
graph
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Insert benchmarks
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
fn bench_insert_flat(c: &mut Criterion) {
|
|
50
|
+
let mut group = c.benchmark_group("insert_flat");
|
|
51
|
+
for n in [1000, 10000, 50000] {
|
|
52
|
+
group.throughput(Throughput::Elements(n as u64));
|
|
53
|
+
group.bench_with_input(BenchmarkId::from_parameter(n), &n, |b, &n| {
|
|
54
|
+
b.iter(|| build_flat(black_box(n)));
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fn bench_insert_hnsw(c: &mut Criterion) {
|
|
60
|
+
let mut group = c.benchmark_group("insert_hnsw");
|
|
61
|
+
for n in [1000, 10000, 50000] {
|
|
62
|
+
group.throughput(Throughput::Elements(n as u64));
|
|
63
|
+
group.bench_with_input(BenchmarkId::from_parameter(n), &n, |b, &n| {
|
|
64
|
+
b.iter(|| build_hnsw(black_box(n)));
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// Search benchmarks (100 queries, avg latency)
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
fn bench_search_flat(c: &mut Criterion) {
|
|
74
|
+
let mut group = c.benchmark_group("search_flat");
|
|
75
|
+
for n in [1000, 10000, 50000] {
|
|
76
|
+
let idx = build_flat(n);
|
|
77
|
+
let queries = random_vectors(100);
|
|
78
|
+
group.throughput(Throughput::Elements(100));
|
|
79
|
+
group.bench_with_input(BenchmarkId::from_parameter(n), &(idx, queries), |b, (idx, queries)| {
|
|
80
|
+
b.iter(|| {
|
|
81
|
+
for q in queries {
|
|
82
|
+
black_box(idx.search(q, 10).unwrap());
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
fn bench_search_hnsw(c: &mut Criterion) {
|
|
90
|
+
let mut group = c.benchmark_group("search_hnsw");
|
|
91
|
+
for n in [1000, 10000, 50000] {
|
|
92
|
+
let graph = build_hnsw(n);
|
|
93
|
+
let queries = random_vectors(100);
|
|
94
|
+
group.throughput(Throughput::Elements(100));
|
|
95
|
+
group.bench_with_input(BenchmarkId::from_parameter(n), &(graph, queries), |b, (graph, queries)| {
|
|
96
|
+
b.iter(|| {
|
|
97
|
+
for q in queries {
|
|
98
|
+
black_box(graph.search(q, 10).unwrap());
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
// Recall benchmark
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
|
|
109
|
+
fn bench_recall_hnsw(c: &mut Criterion) {
|
|
110
|
+
let mut group = c.benchmark_group("recall_hnsw");
|
|
111
|
+
let n = 10000;
|
|
112
|
+
let k = 10;
|
|
113
|
+
|
|
114
|
+
// Build both indexes
|
|
115
|
+
let flat = build_flat(n);
|
|
116
|
+
let hnsw = build_hnsw(n);
|
|
117
|
+
let queries = random_vectors(100);
|
|
118
|
+
|
|
119
|
+
// Compute ground truth with Flat (exact)
|
|
120
|
+
let ground_truth: Vec<Vec<SearchResult>> = queries
|
|
121
|
+
.iter()
|
|
122
|
+
.map(|q| flat.search(q, k).unwrap())
|
|
123
|
+
.collect();
|
|
124
|
+
|
|
125
|
+
group.bench_function("recall@10_vs_flat", |b| {
|
|
126
|
+
b.iter(|| {
|
|
127
|
+
let mut total_hits = 0usize;
|
|
128
|
+
let mut total = 0usize;
|
|
129
|
+
for (q, gt) in queries.iter().zip(ground_truth.iter()) {
|
|
130
|
+
let approx = hnsw.search(q, k).unwrap();
|
|
131
|
+
// Count intersection
|
|
132
|
+
let gt_ids: std::collections::HashSet<u64> = gt.iter().map(|r| r.id).collect();
|
|
133
|
+
total_hits += approx.iter().filter(|r| gt_ids.contains(&r.id)).count();
|
|
134
|
+
total += k;
|
|
135
|
+
}
|
|
136
|
+
let recall = total_hits as f64 / total as f64;
|
|
137
|
+
black_box(recall);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
// Collection persistence benchmark
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
|
|
146
|
+
fn bench_persist_collection(c: &mut Criterion) {
|
|
147
|
+
let mut group = c.benchmark_group("persist_collection");
|
|
148
|
+
let n = 1000;
|
|
149
|
+
|
|
150
|
+
group.bench_function("insert_1000_persist", |b| {
|
|
151
|
+
b.iter(|| {
|
|
152
|
+
let dir = tempfile::tempdir().unwrap();
|
|
153
|
+
let path = dir.path().join("bench.embeddb");
|
|
154
|
+
let pc = std::sync::Arc::new(
|
|
155
|
+
vexra_storage::page_cache::PageCache::open(&path, Default::default()).unwrap(),
|
|
156
|
+
);
|
|
157
|
+
let config = CollectionConfig::new("bench", DIM);
|
|
158
|
+
let mut col = Collection::new_persistent(config, IndexType::Flat, pc).unwrap();
|
|
159
|
+
let vectors = random_vectors(n);
|
|
160
|
+
for (i, v) in vectors.iter().enumerate() {
|
|
161
|
+
col.insert(vexra_core::config::Document::with_vector(
|
|
162
|
+
format!("doc_{}", i), v.clone(),
|
|
163
|
+
))
|
|
164
|
+
.unwrap();
|
|
165
|
+
}
|
|
166
|
+
black_box(col.vector_count());
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
criterion_group!(
|
|
172
|
+
name = benches;
|
|
173
|
+
config = Criterion::default()
|
|
174
|
+
.sample_size(30)
|
|
175
|
+
.measurement_time(Duration::from_secs(10))
|
|
176
|
+
.warm_up_time(Duration::from_secs(2));
|
|
177
|
+
targets =
|
|
178
|
+
bench_insert_flat,
|
|
179
|
+
bench_search_flat,
|
|
180
|
+
bench_insert_hnsw,
|
|
181
|
+
bench_search_hnsw,
|
|
182
|
+
bench_recall_hnsw,
|
|
183
|
+
bench_persist_collection,
|
|
184
|
+
);
|
|
185
|
+
criterion_main!(benches);
|