// Copyright 2021 TiKV Project Authors. Licensed under Apache-2.0.

mod engine;
mod engine_factory;
mod mvcc;
mod storage;
mod txn;

use std::fmt;

use criterion::Criterion;
use tikv::storage::Engine;

use self::{
    engine::bench_engine,
    engine_factory::{BTreeEngineFactory, EngineFactory, StorageBTreeEngineFactory},
    mvcc::bench_mvcc,
    storage::bench_storage,
    txn::bench_txn,
};

const DEFAULT_ITERATIONS: usize = 10;
const DEFAULT_KEY_LENGTHS: [usize; 1] = [64];
const DEFAULT_VALUE_LENGTHS: [usize; 2] = [64, 65];
const DEFAULT_KV_GENERATOR_SEED: u64 = 0;

#[derive(Clone)]
pub struct BenchConfig<F> {
    pub key_length: usize,
    pub value_length: usize,
    pub engine_factory: F,
}

impl<F: fmt::Debug> fmt::Debug for BenchConfig<F> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{:?}_KL{:?}_VL{:?}",
            self.engine_factory, self.key_length, self.value_length
        )
    }
}

pub fn load_configs<E: Engine, F: EngineFactory<E>>(engine_factory: F) -> Vec<BenchConfig<F>> {
    let key_lengths = DEFAULT_KEY_LENGTHS;
    let value_lengths = DEFAULT_VALUE_LENGTHS;
    let mut configs = vec![];

    for &kl in &key_lengths {
        for &vl in &value_lengths {
            configs.push(BenchConfig {
                key_length: kl,
                value_length: vl,
                engine_factory,
            })
        }
    }
    configs
}

fn main() {
    let mut c = Criterion::default().configure_from_args();
    let btree_engine_configs = load_configs(BTreeEngineFactory {});
    let storage_btree_engine_configs = load_configs(StorageBTreeEngineFactory {});

    bench_engine(&mut c, &btree_engine_configs);
    bench_engine(&mut c, &storage_btree_engine_configs);

    bench_mvcc(&mut c, &btree_engine_configs);
    bench_mvcc(&mut c, &storage_btree_engine_configs);

    bench_txn(&mut c, &btree_engine_configs);
    bench_txn(&mut c, &storage_btree_engine_configs);

    bench_storage(&mut c, &btree_engine_configs);
    bench_storage(&mut c, &storage_btree_engine_configs);

    c.final_summary();
}
