diskann_benchmark_runner/
registry.rs1use std::collections::HashMap;
7
8use thiserror::Error;
9
10use crate::{
11 dispatcher::{DispatchRule, Map},
12 output::Sink,
13 Any, Checkpoint, Input, Output,
14};
15
16pub struct Inputs {
18 inputs: HashMap<&'static str, Box<dyn Input>>,
20}
21
22impl Inputs {
23 pub fn new() -> Self {
25 Self {
26 inputs: HashMap::new(),
27 }
28 }
29
30 pub fn get(&self, tag: &str) -> Option<&dyn Input> {
32 match self.inputs.get(tag) {
33 Some(v) => Some(&**v),
34 None => None,
35 }
36 }
37
38 pub fn register<T>(&mut self, input: T) -> anyhow::Result<()>
43 where
44 T: Input + 'static,
45 {
46 use std::collections::hash_map::Entry;
47
48 let tag = input.tag();
49 match self.inputs.entry(tag) {
50 Entry::Vacant(entry) => {
51 entry.insert(Box::new(input));
52 Ok(())
53 }
54 Entry::Occupied(_) => {
55 #[derive(Debug, Error)]
56 #[error("An input with the tag \"{}\" already exists", self.0)]
57 struct AlreadyExists(&'static str);
58
59 Err(anyhow::anyhow!(AlreadyExists(tag)))
60 }
61 }
62 }
63
64 pub fn tags(&self) -> impl ExactSizeIterator<Item = &'static str> + use<'_> {
66 self.inputs.keys().copied()
67 }
68}
69
70impl Default for Inputs {
71 fn default() -> Self {
72 Self::new()
73 }
74}
75
76pub struct Benchmarks {
78 dispatcher: Dispatcher,
79}
80
81impl Benchmarks {
82 pub fn new() -> Self {
84 Self {
85 dispatcher: Dispatcher::new(),
86 }
87 }
88
89 pub fn register<T>(
94 &mut self,
95 name: impl Into<String>,
96 benchmark: impl Fn(T::Type<'_>, Checkpoint<'_>, &mut dyn Output) -> anyhow::Result<serde_json::Value>
97 + 'static,
98 ) where
99 T: for<'a> Map<Type<'a>: DispatchRule<&'a Any>>,
100 {
101 self.dispatcher
102 .register::<_, T, CheckpointRef, DynOutput>(name.into(), benchmark)
103 }
104
105 pub(crate) fn methods(&self) -> impl ExactSizeIterator<Item = &(String, Method)> {
106 self.dispatcher.methods()
107 }
108
109 pub fn has_match(&self, job: &Any) -> bool {
111 let sink: &mut dyn Output = &mut Sink::new();
112 self.dispatcher.has_match(&job, &Checkpoint::empty(), &sink)
113 }
114
115 pub fn call(
122 &self,
123 job: &Any,
124 checkpoint: Checkpoint<'_>,
125 output: &mut dyn Output,
126 ) -> anyhow::Result<serde_json::Value> {
127 self.dispatcher.call(job, checkpoint, output).unwrap()
128 }
129
130 pub fn debug(&self, job: &Any, methods: usize) -> Result<(), Vec<Mismatch>> {
139 let checkpoint = Checkpoint::empty();
140 let sink: &mut dyn Output = &mut Sink::new();
141 let mismatches = match self.dispatcher.debug(methods, &job, &checkpoint, &sink) {
142 Ok(()) => return Ok(()),
143 Err(mismatches) => mismatches,
144 };
145
146 Err(mismatches
149 .into_iter()
150 .map(|m| {
151 let reason = m.mismatches()[0]
152 .as_ref()
153 .map(|opt| opt.to_string())
154 .unwrap_or("<missing>".into());
155 Mismatch {
156 method: m.method().to_string(),
157 reason,
158 }
159 })
160 .collect())
161 }
162}
163
164impl Default for Benchmarks {
165 fn default() -> Self {
166 Self::new()
167 }
168}
169
170pub struct Mismatch {
172 method: String,
173 reason: String,
174}
175
176impl Mismatch {
177 pub fn method(&self) -> &str {
179 &self.method
180 }
181
182 pub fn reason(&self) -> &str {
184 &self.reason
185 }
186}
187
188pub(crate) struct DynOutput;
194
195impl Map for DynOutput {
196 type Type<'a> = &'a mut dyn Output;
197}
198
199#[derive(Debug, Clone, Copy)]
201pub(crate) struct CheckpointRef;
202
203impl Map for CheckpointRef {
204 type Type<'a> = Checkpoint<'a>;
205}
206
207type Dispatcher = crate::dispatcher::Dispatcher3<
209 anyhow::Result<serde_json::Value>,
210 crate::dispatcher::Ref<Any>,
211 CheckpointRef,
212 DynOutput,
213>;
214
215type Method = Box<
217 dyn crate::dispatcher::Dispatch3<
218 anyhow::Result<serde_json::Value>,
219 crate::dispatcher::Ref<Any>,
220 CheckpointRef,
221 DynOutput,
222 >,
223>;