#![cfg(not(feature = "parallel"))]
#![allow(clippy::unwrap_used)]
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use iqdb_flat::{FlatConfig, FlatIndex};
use iqdb_index::{Index, IndexCore};
use iqdb_types::{DistanceMetric, SearchParams, VectorId};
use std::sync::Arc;
fn arc(v: &[f32]) -> Arc<[f32]> {
Arc::from(v)
}
static ALLOC_COUNT: AtomicUsize = AtomicUsize::new(0);
static COUNTING: AtomicBool = AtomicBool::new(false);
struct CountingAlloc;
unsafe impl GlobalAlloc for CountingAlloc {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if COUNTING.load(Ordering::Relaxed) {
let _ = ALLOC_COUNT.fetch_add(1, Ordering::Relaxed);
}
unsafe { System.alloc(layout) }
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
unsafe { System.dealloc(ptr, layout) }
}
}
#[global_allocator]
static GLOBAL: CountingAlloc = CountingAlloc;
fn build_index(n: usize) -> FlatIndex {
let mut idx = FlatIndex::new(8, DistanceMetric::Euclidean, FlatConfig).unwrap();
for i in 0..n {
let v: Vec<f32> = (0..8).map(|j| (i as f32 + j as f32) * 0.01).collect();
idx.insert(VectorId::from(i as u64), arc(&v), None).unwrap();
}
idx
}
fn count_search_allocs(idx: &FlatIndex, query: &[f32], params: &SearchParams) -> usize {
ALLOC_COUNT.store(0, Ordering::Relaxed);
COUNTING.store(true, Ordering::Relaxed);
let _hits = idx.search(query, params).unwrap();
COUNTING.store(false, Ordering::Relaxed);
ALLOC_COUNT.load(Ordering::Relaxed)
}
#[test]
fn filter_none_search_alloc_count_does_not_scale_with_n() {
let small = build_index(128);
let large = build_index(8_192);
let query = vec![0.0_f32; 8];
let params = SearchParams::new(10, DistanceMetric::Euclidean);
let _ = small.search(&query, ¶ms).unwrap();
let _ = large.search(&query, ¶ms).unwrap();
let small_count = count_search_allocs(&small, &query, ¶ms);
let large_count = count_search_allocs(&large, &query, ¶ms);
assert_eq!(
small_count, large_count,
"filter-None search allocation count must be N-independent: \
N=128 -> {small_count}, N=8192 -> {large_count}",
);
}