use std::num::NonZeroUsize;
use anyhow::Context;
use diskann_benchmark_runner::{files::InputFile, utils::datatype::DataType, Checker};
use serde::{Deserialize, Serialize};
use crate::{
inputs::{as_input, write_field, Example, PRINT_WIDTH},
utils::SimilarityMeasure,
};
as_input!(FlatSearch);
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct FlatSearch {
pub(crate) data: InputFile,
pub(crate) data_type: DataType,
pub(crate) distance: SimilarityMeasure,
pub(crate) search: SearchPhase,
}
impl FlatSearch {
pub(crate) const fn tag() -> &'static str {
"flat-search"
}
pub(crate) fn validate(&mut self, checker: &mut Checker) -> anyhow::Result<()> {
self.data.resolve(checker)?;
self.search.validate(checker)?;
Ok(())
}
}
impl std::fmt::Display for FlatSearch {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write_field!(f, "Data", self.data.display())?;
write_field!(f, "Data Type", self.data_type)?;
write_field!(f, "Distance", self.distance)?;
write_field!(f, "Queries", self.search.queries.display())?;
write_field!(f, "Groundtruth", self.search.groundtruth.display())?;
write_field!(f, "K", self.search.k)?;
write_field!(
f,
"Threads",
self.search
.num_threads
.iter()
.map(|t| t.to_string())
.collect::<Vec<_>>()
.join(", ")
)?;
write_field!(f, "Reps", self.search.reps)?;
Ok(())
}
}
impl Example for FlatSearch {
fn example() -> Self {
Self {
data: InputFile::new("path/to/data.bin"),
data_type: DataType::Float32,
distance: SimilarityMeasure::SquaredL2,
search: SearchPhase::example(),
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct SearchPhase {
pub(crate) queries: InputFile,
pub(crate) groundtruth: InputFile,
pub(crate) k: NonZeroUsize,
pub(crate) num_threads: Vec<NonZeroUsize>,
pub(crate) reps: NonZeroUsize,
}
impl SearchPhase {
pub(crate) fn validate(&mut self, checker: &mut Checker) -> anyhow::Result<()> {
self.queries
.resolve(checker)
.context("resolving queries file")?;
self.groundtruth
.resolve(checker)
.context("resolving groundtruth file")?;
Ok(())
}
}
impl Example for SearchPhase {
fn example() -> Self {
Self {
queries: InputFile::new("path/to/queries.bin"),
groundtruth: InputFile::new("path/to/groundtruth.bin"),
k: NonZeroUsize::new(10).unwrap(),
num_threads: vec![
NonZeroUsize::new(1).unwrap(),
NonZeroUsize::new(4).unwrap(),
NonZeroUsize::new(8).unwrap(),
],
reps: NonZeroUsize::new(5).unwrap(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::inputs::Example;
#[test]
fn example_flat_search_round_trips() {
let example = FlatSearch::example();
let json = serde_json::to_value(&example).unwrap();
let _: FlatSearch = serde_json::from_value(json).unwrap();
}
#[test]
fn display_flat_search() {
let example = FlatSearch::example();
let text = format!("{}", example);
assert!(text.contains("Data"));
assert!(text.contains("Threads"));
assert!(text.contains("Reps"));
}
}