Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6ded6e4
Checkpoint.
May 27, 2026
7a16b93
Checkpoint.
Jun 11, 2026
784ff09
Merge remote-tracking branch 'origin/main' into mhildebr/reflect
Sep 25, 2026
6f735df
Checkpoint.
Sep 25, 2026
502e154
Enum?
Sep 25, 2026
57c5c33
More derives!
Sep 25, 2026
a91e2c9
Progress!
Sep 26, 2026
4598bc1
Let's see if we can wire it up ...
Sep 26, 2026
0deff77
Refactor
Sep 26, 2026
84097c3
Clean-up.
Sep 26, 2026
fae0fe9
Slowly expanding.
Sep 26, 2026
979d84f
Serde tests.
Sep 28, 2026
9e81f18
Checkpoint.
Sep 28, 2026
288505f
More progress?
Sep 28, 2026
8b2d91e
`diskann-benchmark-simd`.
Sep 28, 2026
900cc26
Registry tests.
Sep 29, 2026
0530df6
trybuild test and docs.
Sep 30, 2026
89f5ace
minimal CLI hookup.
Sep 30, 2026
a550a07
CLI baselines.
Sep 30, 2026
8a29df9
CLoser!
Oct 1, 2026
78a2698
Finish porting.
Oct 1, 2026
3036872
Remove temp files.
Oct 1, 2026
dee0443
Merge remote-tracking branch 'origin/main' into mhildebr/reflect
Oct 3, 2026
fea7ce4
Prepare to remove internal tagging.
Oct 4, 2026
d76c0ef
Prepare for implementation overhaul.
Oct 8, 2026
9ae63ee
Move to new impl.
Oct 8, 2026
2961e80
Checkpoint.
Oct 8, 2026
cd7bdb0
Big overhaul.
Oct 9, 2026
9490d2d
Reorg.
Oct 9, 2026
1bddeb4
Rename
Oct 9, 2026
a9302a8
AAAAHHHHHH
Oct 9, 2026
67ed305
Partial support for tolerance inputs.
Oct 9, 2026
1a22016
Consolidate benchmark input type erasure.
Oct 9, 2026
7522c15
Add small docs.
Oct 9, 2026
b79e8bf
Finish the job.
Oct 9, 2026
8f04748
Merge remote-tracking branch 'origin/main' into mhildebr/reflect
Oct 9, 2026
1da8230
Merge remote-tracking branch 'origin/mhildebr/simplify-input' into mh…
Oct 10, 2026
69df89f
Rename again.
Oct 13, 2026
4e5e51e
Merge remote-tracking branch 'origin/main' into mhildebr/reflect
Oct 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ members = [
"diskann-record",
"diskann-tools",
"diskann-bftree",
"diskann-macros",
]

default-members = [
Expand Down Expand Up @@ -66,6 +67,7 @@ diskann-inmem = { path = "diskann-inmem", default-features = false, version = "0
diskann-disk = { path = "diskann-disk", version = "0.60.0" }
diskann-label-filter = { path = "diskann-label-filter", version = "0.60.0" }
# Infra
diskann-macros = { path = "diskann-macros", version = "0.60.0" }
diskann-benchmark-runner = { path = "diskann-benchmark-runner", version = "0.60.0" }
diskann-benchmark-core = { path = "diskann-benchmark-core", version = "0.60.0" }
diskann-tools = { path = "diskann-tools", version = "0.60.0" }
Expand Down
3 changes: 3 additions & 0 deletions diskann-benchmark-runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ edition = "2024"
[dependencies]
anyhow = { workspace = true }
clap = { workspace = true, features = ["derive"] }
diskann-macros = { workspace = true }
half = { workspace = true }
hashbrown = { workspace = true }
indicatif = "0.18.3"
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
Expand All @@ -25,6 +27,7 @@ expect_used = "warn"
panic = "warn"

[dev-dependencies]
diskann-utils = { workspace = true, default-features = false, features = ["testing"] }
tempfile.workspace = true

[features]
Expand Down
8 changes: 7 additions & 1 deletion diskann-benchmark-runner/dev/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ fn main() -> anyhow::Result<()> {
#[derive(Debug, clap::Parser)]
struct Cli {
/// Emulate enabling various features for feature gated functionality.
#[arg(long, value_delimiter = ',', num_args = 0..)]
///
/// Currently available features:
/// * `gated-feature-0`
/// * `gated-feature-1`
/// * `gated-feature-2`
/// * `gated-feature-3`
#[arg(long, value_delimiter = ',', num_args = 1)]
features: Vec<String>,

/// The actual application.
Expand Down
101 changes: 56 additions & 45 deletions diskann-benchmark-runner/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ pub enum Commands {
},
#[command(subcommand)]
Check(Check),
/// Provide information about all registered types.
TypeInfo {
/// Provide information for the given type.
describe: Option<String>,
},
}

/// Subcommands for regression check operations.
Expand Down Expand Up @@ -207,12 +212,28 @@ impl App {
if let Some(describe) = describe {
if let Some(input) = registry.input(describe) {
let repr = jobs::Unprocessed::format_input(input)?;

// Render JSON.
writeln!(
output,
"The example JSON representation for \"{}\" is:",
"The example JSON representation for \"{}\" is:\n",
describe
)?;
writeln!(output, "{}", serde_json::to_string_pretty(&repr)?)?;

// Render Type Info.
match input.raw_reflection() {
Some(reflection) => {
writeln!(output, "\nType Information:\n\n{}", reflection.render())?;

writeln!(
output,
"More type information available using `type-info`"
)?;
}
None => writeln!(output, "\n\nNo Type Information Available")?,
}

return Ok(());
} else {
writeln!(output, "No input found for \"{}\"", describe)?;
Expand Down Expand Up @@ -386,6 +407,11 @@ impl App {
}
// Extensions
Commands::Check(check) => return self.check(check, registry, output),

// Types
Commands::TypeInfo { describe } => {
self.type_info(describe.as_deref(), registry, output)?
}
};
Ok(())
}
Expand Down Expand Up @@ -482,6 +508,29 @@ impl App {
}
}
}

fn type_info(
&self,
describe: Option<&str>,
registry: &registry::Registry,
mut output: &mut dyn Output,
) -> anyhow::Result<()> {
match describe {
Some(type_name) => match registry.type_info(type_name) {
Some(reflection) => writeln!(output, "{}", reflection.render())?,
None => anyhow::bail!("No type information for \"{}\"", type_name),
},
None => {
let mut all_types: Vec<_> = registry.type_names().collect();
all_types.sort_unstable();
writeln!(output, "All registered types:")?;
for type_name in all_types {
writeln!(output, " {}", type_name)?;
}
}
}
Ok(())
}
}

///////////
Expand Down Expand Up @@ -541,8 +590,6 @@ mod tests {

use crate::{registry, test::TestConfig, ux};

const ENV: &str = "DISKANN_TEST";

// Expected I/O files.
const STDIN: &str = "stdin.txt";
const STDOUT: &str = "stdout.txt";
Expand All @@ -560,42 +607,6 @@ mod tests {

const ALL_GENERATED_OUTPUTS: [&str; 2] = [OUTPUT_FILE, CHECK_OUTPUT_FILE];

// Read the entire contents of a file to a string.
fn read_to_string<P: AsRef<Path>>(path: P, ctx: &str) -> String {
match std::fs::read_to_string(path.as_ref()) {
Ok(s) => ux::normalize(s),
Err(err) => panic!(
"failed to read {} {:?} with error: {}",
ctx,
path.as_ref(),
err
),
}
}

// Check if `DISKANN_TEST=overwrite` is configured. Return `true` if so - otherwise
// return `false`.
//
// If `DISKANN_TEST` is set but its value is not `overwrite` - panic.
fn overwrite() -> bool {
match std::env::var(ENV) {
Ok(v) => {
if v == "overwrite" {
true
} else {
panic!(
"Unknown value for {}: \"{}\". Expected \"overwrite\"",
ENV, v
);
}
}
Err(std::env::VarError::NotPresent) => false,
Err(std::env::VarError::NotUnicode(_)) => {
panic!("Value for {} is not unicode", ENV);
}
}
}

// Test Runner
struct Test {
dir: PathBuf,
Expand All @@ -606,15 +617,15 @@ mod tests {
fn new(dir: &Path) -> Self {
Self {
dir: dir.into(),
overwrite: overwrite(),
overwrite: ux::test::overwrite(),
}
}

fn parse_stdin(&self, tempdir: &Path) -> Vec<App> {
let path = self.dir.join(STDIN);

// Read the standard input file to a string.
let stdin = read_to_string(&path, "standard input");
let stdin = ux::test::read_to_string(&path, "standard input");

let output: Vec<App> = stdin
.lines()
Expand Down Expand Up @@ -723,7 +734,7 @@ mod tests {
if self.overwrite {
std::fs::write(output, stdout).unwrap();
} else {
let expected = read_to_string(&output, "expected standard output");
let expected = ux::test::read_to_string(&output, "expected standard output");
if stdout != expected {
panic!("Got:\n--\n{}\n--\nExpected:\n--\n{}\n--", stdout, expected);
}
Expand Down Expand Up @@ -765,9 +776,9 @@ mod tests {
} else {
match (was_generated, is_expected) {
(true, true) => {
let output_contents = read_to_string(generated_path, "generated");
let output_contents = ux::test::read_to_string(generated_path, "generated");

let expected_contents = read_to_string(expected_path, "expected");
let expected_contents = ux::test::read_to_string(expected_path, "expected");

if output_contents != expected_contents {
panic!(
Expand All @@ -777,7 +788,7 @@ mod tests {
}
}
(true, false) => {
let output_contents = read_to_string(generated_path, "generated");
let output_contents = ux::test::read_to_string(generated_path, "generated");

panic!(
"{} was generated when none was expected. Contents:\n\n{}",
Expand Down
12 changes: 11 additions & 1 deletion diskann-benchmark-runner/src/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};

use serde::{Deserialize, Serialize};

use super::Checker;
use crate::{Checker, Reflect};

/// A file that is used as an input to for a benchmark.
///
Expand All @@ -27,6 +27,16 @@ pub struct InputFile {
path: PathBuf,
}

impl Reflect for InputFile {
fn ty() -> crate::reflect::Type {
<PathBuf as Reflect>::ty()
}

fn format_type_name(f: &mut dyn std::fmt::Write) -> std::fmt::Result {
f.write_str("benchmark::InputFile")
}
}

impl InputFile {
/// Create a new input file from the path-like `path`.
pub fn new<P>(path: P) -> Self
Expand Down
17 changes: 14 additions & 3 deletions diskann-benchmark-runner/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT license.
*/

use crate::Checker;
use crate::{Checker, Reflect};

/// Inputs to [`Benchmarks`](crate::Benchmark).
///
Expand All @@ -16,7 +16,7 @@ pub trait Input: Sized + std::fmt::Debug + 'static {
/// [`Deserialize`](serde::Deserialize) implementation.
///
/// Final object validation is performed via [`from_raw`](Self::from_raw).
type Raw: serde::de::DeserializeOwned + serde::Serialize;
type Raw: serde::de::DeserializeOwned + serde::Serialize + Reflect;

/// Return the discriminant associated with this type.
///
Expand All @@ -39,7 +39,7 @@ pub trait Input: Sized + std::fmt::Debug + 'static {
}

pub(crate) mod internal {
use crate::{Checker, Features, internal::visibility::Visibility};
use crate::{Checker, Features, Reflection, internal::visibility::Visibility};

/// Runtime representation of a deserialized [`Input`].
#[derive(Debug)]
Expand Down Expand Up @@ -145,6 +145,10 @@ pub(crate) mod internal {
self.0.visibility()
}

pub(crate) fn raw_reflection(&self) -> Option<Reflection> {
self.0.raw_reflection()
}

pub(crate) fn as_any(&self) -> &dyn std::any::Any {
self.0.as_any()
}
Expand Down Expand Up @@ -221,6 +225,7 @@ pub(crate) mod internal {
fn visibility(&self) -> Visibility<'_>;

// reflection
fn raw_reflection(&self) -> Option<Reflection>;
fn as_any(&self) -> &dyn std::any::Any;
fn type_name(&self) -> &'static str;
}
Expand Down Expand Up @@ -261,6 +266,9 @@ pub(crate) mod internal {
fn visibility(&self) -> Visibility<'_> {
Visibility::Available
}
fn raw_reflection(&self) -> Option<Reflection> {
Some(Reflection::new::<T::Raw>())
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
Expand Down Expand Up @@ -305,6 +313,9 @@ pub(crate) mod internal {
features: &self.features,
}
}
fn raw_reflection(&self) -> Option<Reflection> {
None
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
Expand Down
1 change: 1 addition & 0 deletions diskann-benchmark-runner/src/internal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use anyhow::Context;

pub(crate) mod regression;
pub(crate) mod typemap;
pub(crate) mod visibility;

/// Attempt to load and deserialize from a JSON file on disk identified with `path`.
Expand Down
Loading
Loading