use std::time::Instant;
fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::WARN)
.init();
let cache = std::env::var_os("BOBINE_CACHE_DIR")
.map(std::path::PathBuf::from)
.unwrap_or_else(|| std::env::temp_dir().join("bobine_test").join("cache"));
let mut args: Vec<String> = std::env::args().skip(1).collect();
let int8 = args.iter().position(|a| a == "--int8");
if let Some(pos) = int8 {
args.remove(pos);
}
if args.is_empty() {
eprintln!("usage: bench_texteller [--int8] <image.png> [...]");
std::process::exit(2);
}
let providers: Vec<String> = std::env::var("BOBINE_ORT_PROVIDERS")
.unwrap_or_default()
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect();
let enc_providers: Vec<String> = std::env::var("BOBINE_ORT_ENCODER_PROVIDERS")
.unwrap_or_default()
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect();
let t0 = Instant::now();
let mut tt = if int8.is_some() {
bobine::TexTeller::from_pretrained_int8_split(
&cache,
if enc_providers.is_empty() {
None
} else {
Some(&enc_providers)
},
&providers,
)?
} else {
bobine::TexTeller::from_pretrained_split(
"OleehyO/TexTeller",
&cache,
bobine::ModelPrecision::Fp32,
if enc_providers.is_empty() {
None
} else {
Some(&enc_providers)
},
&providers,
)?
};
println!(
"model load ({}, dec={:?}, enc={:?}): {:?}",
if int8.is_some() { "int8" } else { "fp32+kv" },
providers,
if enc_providers.is_empty() {
std::borrow::Cow::Borrowed("<inherit>")
} else {
std::borrow::Cow::Owned(format!("{enc_providers:?}"))
},
t0.elapsed()
);
for path in &args {
let warm = tt.recognize(std::path::Path::new(path))?;
let mut best = f64::MAX;
let mut last = String::new();
for _ in 0..3 {
let s = Instant::now();
let latex = tt.recognize(std::path::Path::new(path))?;
best = best.min(s.elapsed().as_secs_f64());
last = latex;
}
println!("--- {} ({:.2}s/run)", path, best);
println!("warmup: {warm}");
println!("latex : {last}");
}
Ok(())
}