mdict-rs 0.1.4

Library-first Rust parser for MDict .mdx and .mdd dictionaries
Documentation
use std::env;
use std::time::Instant;

use mdict_rs::{MddFile, MdxFile};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut args = env::args().skip(1);
    let mdx_path = args
        .next()
        .ok_or("usage: bench_local <mdx_path> <mdd_path>")?;
    let mdd_path = args
        .next()
        .ok_or("usage: bench_local <mdx_path> <mdd_path>")?;

    let open_start = Instant::now();
    let mdx = MdxFile::open(&mdx_path)?;
    let mdx_open = open_start.elapsed();

    let queries = ["apple", "book", "zebra", "Apple"];
    let lookup_start = Instant::now();
    let mut total_chars = 0usize;
    for query in queries {
        let record = mdx.lookup(query)?.ok_or("missing benchmark MDX key")?;
        total_chars += record.text.len();
    }
    let mdx_lookup = lookup_start.elapsed();

    let key_scan_start = Instant::now();
    let mut mdx_key_count = 0usize;
    let mut mdx_key_bytes = 0usize;
    for key in mdx.keys() {
        let key = key?;
        mdx_key_count += 1;
        mdx_key_bytes += key.len();
    }
    let mdx_key_scan = key_scan_start.elapsed();

    let entry_scan_start = Instant::now();
    let mut mdx_entry_count = 0usize;
    let mut mdx_entry_key_bytes = 0usize;
    let mut mdx_entry_text_bytes = 0usize;
    for entry in mdx.entries() {
        let entry = entry?;
        mdx_entry_count += 1;
        mdx_entry_key_bytes += entry.key.len();
        mdx_entry_text_bytes += entry.text.len();
    }
    let mdx_entry_scan = entry_scan_start.elapsed();

    let open_start = Instant::now();
    let mdd = MddFile::open(&mdd_path)?;
    let mdd_open = open_start.elapsed();

    let lookup_start = Instant::now();
    let css = mdd
        .lookup("\\LM5style.css")?
        .ok_or("missing benchmark MDD key")?;
    let mdd_lookup = lookup_start.elapsed();

    let key_scan_start = Instant::now();
    let mut mdd_key_count = 0usize;
    let mut mdd_key_bytes = 0usize;
    for key in mdd.keys() {
        let key = key?;
        mdd_key_count += 1;
        mdd_key_bytes += key.len();
    }
    let mdd_key_scan = key_scan_start.elapsed();

    let entry_scan_start = Instant::now();
    let mut mdd_entry_count = 0usize;
    let mut mdd_entry_key_bytes = 0usize;
    let mut mdd_entry_data_bytes = 0usize;
    for entry in mdd.entries() {
        let entry = entry?;
        mdd_entry_count += 1;
        mdd_entry_key_bytes += entry.key.len();
        mdd_entry_data_bytes += entry.data.len();
    }
    let mdd_entry_scan = entry_scan_start.elapsed();

    println!("mdx_open_ms={}", mdx_open.as_millis());
    println!("mdx_lookup_ms_total={}", mdx_lookup.as_millis());
    println!(
        "mdx_lookup_ms_avg={:.2}",
        mdx_lookup.as_secs_f64() * 1000.0 / queries.len() as f64
    );
    println!("mdx_total_chars={total_chars}");
    println!("mdx_keys_scan_ms_total={}", mdx_key_scan.as_millis());
    println!("mdx_keys_scan_count={mdx_key_count}");
    println!("mdx_keys_scan_total_bytes={mdx_key_bytes}");
    println!("mdx_entries_scan_ms_total={}", mdx_entry_scan.as_millis());
    println!("mdx_entries_scan_count={mdx_entry_count}");
    println!("mdx_entries_scan_key_bytes={mdx_entry_key_bytes}");
    println!("mdx_entries_scan_text_bytes={mdx_entry_text_bytes}");
    println!("mdd_open_ms={}", mdd_open.as_millis());
    println!("mdd_lookup_ms_total={}", mdd_lookup.as_millis());
    println!("mdd_css_bytes={}", css.data.len());
    println!("mdd_keys_scan_ms_total={}", mdd_key_scan.as_millis());
    println!("mdd_keys_scan_count={mdd_key_count}");
    println!("mdd_keys_scan_total_bytes={mdd_key_bytes}");
    println!("mdd_entries_scan_ms_total={}", mdd_entry_scan.as_millis());
    println!("mdd_entries_scan_count={mdd_entry_count}");
    println!("mdd_entries_scan_key_bytes={mdd_entry_key_bytes}");
    println!("mdd_entries_scan_data_bytes={mdd_entry_data_bytes}");

    Ok(())
}