use criterion::{Criterion, black_box, criterion_group, criterion_main};
use rand::Rng;
use astraea_core::types::{DistanceMetric, NodeId};
use astraea_vector::distance::{cosine_distance, euclidean_distance};
use astraea_vector::hnsw::HnswIndex;
const DIM: usize = 128;
const INDEX_SIZE: usize = 1000;
fn random_vector(rng: &mut impl Rng, dim: usize) -> Vec<f32> {
(0..dim).map(|_| rng.r#gen::<f32>()).collect()
}
fn build_index(dim: usize, count: usize) -> HnswIndex {
let mut rng = rand::thread_rng();
let mut index = HnswIndex::new(dim, DistanceMetric::Euclidean, 16, 200);
for i in 0..count {
let vec = random_vector(&mut rng, dim);
index.insert(NodeId(i as u64), &vec).unwrap();
}
index
}
fn vector_benchmarks(c: &mut Criterion) {
let mut group = c.benchmark_group("vector");
group.bench_function("hnsw_insert", |b| {
let mut rng = rand::thread_rng();
let mut index = build_index(DIM, INDEX_SIZE);
let mut next_id = INDEX_SIZE as u64;
b.iter(|| {
let vec = random_vector(&mut rng, DIM);
index.insert(NodeId(next_id), black_box(&vec)).unwrap();
next_id += 1;
});
});
group.bench_function("hnsw_search_k10", |b| {
let index = build_index(DIM, INDEX_SIZE);
let mut rng = rand::thread_rng();
b.iter(|| {
let query = random_vector(&mut rng, DIM);
black_box(index.search(black_box(&query), 10, 50).unwrap());
});
});
group.bench_function("hnsw_search_k50", |b| {
let index = build_index(DIM, INDEX_SIZE);
let mut rng = rand::thread_rng();
b.iter(|| {
let query = random_vector(&mut rng, DIM);
black_box(index.search(black_box(&query), 50, 100).unwrap());
});
});
group.bench_function("cosine_distance_128", |b| {
let mut rng = rand::thread_rng();
let a = random_vector(&mut rng, DIM);
let b_vec = random_vector(&mut rng, DIM);
b.iter(|| {
black_box(cosine_distance(black_box(&a), black_box(&b_vec)).unwrap());
});
});
group.bench_function("euclidean_distance_128", |b| {
let mut rng = rand::thread_rng();
let a = random_vector(&mut rng, DIM);
let b_vec = random_vector(&mut rng, DIM);
b.iter(|| {
black_box(euclidean_distance(black_box(&a), black_box(&b_vec)).unwrap());
});
});
group.finish();
}
criterion_group!(benches, vector_benchmarks);
criterion_main!(benches);