aboutsummaryrefslogtreecommitdiffstats
path: root/autere_db/benches
diff options
context:
space:
mode:
Diffstat (limited to 'autere_db/benches')
-rw-r--r--autere_db/benches/benchmark.rs181
-rw-r--r--autere_db/benches/utils.rs122
2 files changed, 303 insertions, 0 deletions
diff --git a/autere_db/benches/benchmark.rs b/autere_db/benches/benchmark.rs
new file mode 100644
index 0000000..648c9f6
--- /dev/null
+++ b/autere_db/benches/benchmark.rs
@@ -0,0 +1,181 @@
+mod utils;
+
+use std::collections::HashSet;
+
+use autere_db::*;
+use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
+use tempfile;
+use utils::*;
+
+pub fn upsert_compacted(c: &mut Criterion) {
+ let mut group = c.benchmark_group("upsert_compacted");
+ let data_dir_obj = tempfile::tempdir().expect("Failed to get tmpdir");
+ let data_dir = data_dir_obj
+ .path()
+ .to_str()
+ .expect("Failed to convert tmpdir path to str");
+ let mut db = DB::configure()
+ .fields(Inst::fields())
+ .primary_key(Inst::primary_key())
+ .secondary_keys(Inst::secondary_keys())
+ .data_dir(data_dir)
+ .initialize()
+ .expect("Failed to initialize DB");
+
+ let mut insts = Vec::new();
+ for size in [100_000, 1_000_000, 10_000_000] {
+ println!("Prefilling DB to {} entries", size);
+ prefill_db(&mut db, &mut insts, size, true).expect("Failed to prefill DB");
+
+ group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &_size| {
+ b.iter(|| {
+ let inst = random_inst(0, size as i64 + 1);
+ let result = db.upsert(black_box(inst)).unwrap();
+ assert!(result == ());
+ });
+ });
+ }
+}
+
+pub fn delete_existing_compacted(c: &mut Criterion) {
+ let mut group = c.benchmark_group("delete_existing_compacted");
+ let data_dir_obj = tempfile::tempdir().expect("Failed to get tmpdir");
+ let data_dir = data_dir_obj
+ .path()
+ .to_str()
+ .expect("Failed to convert tmpdir path to str");
+ let mut db = DB::configure()
+ .fields(Inst::fields())
+ .primary_key(Inst::primary_key())
+ .secondary_keys(Inst::secondary_keys())
+ .data_dir(data_dir)
+ .initialize()
+ .expect("Failed to initialize DB");
+
+ let mut insts = Vec::new();
+ for size in [100_000, 1_000_000, 10_000_000] {
+ println!("Prefilling DB to {} entries", size);
+ prefill_db(&mut db, &mut insts, size, true).expect("Failed to prefill DB");
+
+ let pk_set: HashSet<i64> = insts.iter().map(|inst| inst.id).collect();
+ let mut pk_set_it = pk_set.into_iter();
+
+ group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &_size| {
+ b.iter(|| {
+ let result = db
+ .delete(black_box(&Value::Int(pk_set_it.next().unwrap())))
+ .unwrap();
+ assert!(result.is_some());
+ });
+ });
+ }
+}
+
+pub fn upsert_write_durability(c: &mut Criterion) {
+ let mut group = c.benchmark_group("upsert_write_durability");
+
+ for mode in [WriteDurability::Flush, WriteDurability::FlushSync] {
+ group.bench_with_input(BenchmarkId::from_parameter(&mode), &mode, |b, _mode| {
+ let data_dir_obj = tempfile::tempdir().expect("Failed to get tmpdir");
+ let data_dir = data_dir_obj
+ .path()
+ .to_str()
+ .expect("Failed to convert tmpdir path to str");
+ let mut db = DB::configure()
+ .fields(Inst::fields())
+ .primary_key(Inst::primary_key())
+ .secondary_keys(Inst::secondary_keys())
+ .data_dir(data_dir)
+ .write_durability(mode.clone())
+ .initialize()
+ .expect("Failed to initialize DB");
+
+ b.iter(|| {
+ let inst = random_inst(0, 1000);
+ let result = db.upsert(black_box(inst)).unwrap();
+ assert!(result == ());
+ });
+ });
+ }
+}
+
+pub fn get_existing_compacted(c: &mut Criterion) {
+ let mut group = c.benchmark_group("get_existing_compacted");
+
+ let data_dir_obj = tempfile::tempdir().expect("Failed to get tmpdir");
+ let data_dir = data_dir_obj
+ .path()
+ .to_str()
+ .expect("Failed to convert tmpdir path to str");
+ let mut db = DB::configure()
+ .fields(Inst::fields())
+ .primary_key(Inst::primary_key())
+ .secondary_keys(Inst::secondary_keys())
+ .data_dir(data_dir)
+ .initialize()
+ .expect("Failed to initialize DB");
+
+ let mut insts = Vec::new();
+ let mut inst_index = 0;
+ for size in [100_000, 1_000_000, 10_000_000] {
+ println!("Prefilling DB to {} entries", size);
+ prefill_db(&mut db, &mut insts, size, true).expect("Failed to prefill DB");
+
+ group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &_size| {
+ b.iter(|| {
+ let id = insts[inst_index].id;
+ let result = db.get(black_box(&Value::Int(id))).unwrap();
+ assert!(result.is_some());
+ inst_index = (inst_index + 1) % insts.len();
+ });
+ });
+ }
+}
+
+pub fn find_by_existing_compacted(c: &mut Criterion) {
+ let mut group = c.benchmark_group("find_by_existing_compacted");
+
+ let data_dir_path = tempfile::tempdir()
+ .expect("Failed to get tmpdir")
+ .into_path();
+ let data_dir = data_dir_path
+ .to_str()
+ .expect("Failed to convert tmpdir path to str");
+ let mut db = DB::configure()
+ .fields(Inst::fields())
+ .primary_key(Inst::primary_key())
+ .secondary_keys(Inst::secondary_keys())
+ .data_dir(data_dir)
+ .initialize()
+ .expect("Failed to initialize DB");
+
+ let mut insts = Vec::new();
+ let mut inst_index = 0;
+ for size in [100_000, 1_000_000, 10_000_000] {
+ println!("Prefilling DB to {} entries", size);
+ prefill_db(&mut db, &mut insts, size, true).expect("Failed to prefill DB");
+ println!("DB prefilling done, insts.len = {}", insts.len());
+
+ group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &_size| {
+ b.iter(|| {
+ let name = insts[inst_index].name.clone();
+ let result = db
+ .find_by(black_box(&Field::Name), black_box(&Value::String(name)))
+ .unwrap();
+ assert!(result.len() > 0);
+ inst_index = (inst_index + 1) % insts.len();
+ });
+ });
+ }
+}
+
+// Register the benchmark group
+criterion_group!(
+ benches,
+ upsert_compacted,
+ delete_existing_compacted,
+ upsert_write_durability,
+ get_existing_compacted,
+ find_by_existing_compacted,
+);
+criterion_main!(benches);
diff --git a/autere_db/benches/utils.rs b/autere_db/benches/utils.rs
new file mode 100644
index 0000000..9b0a0ea
--- /dev/null
+++ b/autere_db/benches/utils.rs
@@ -0,0 +1,122 @@
+use autere_db::*;
+use rand::distributions::Alphanumeric;
+use rand::Rng;
+use std::fmt::Debug;
+
+#[derive(Eq, PartialEq, Clone, Debug)]
+pub enum Field {
+ Id,
+ Name,
+ Data,
+}
+
+#[derive(PartialEq, Eq, Debug, Clone)]
+pub struct Inst {
+ pub id: i64,
+ pub name: String,
+ pub data: Vec<u8>,
+}
+
+impl AsRef<str> for Field {
+ fn as_ref(&self) -> &str {
+ match self {
+ Field::Id => "id",
+ Field::Name => "name",
+ Field::Data => "data",
+ }
+ }
+}
+
+impl Into<String> for Field {
+ fn into(self) -> String {
+ self.as_ref().to_string()
+ }
+}
+
+impl From<Inst> for Record {
+ fn from(inst: Inst) -> Self {
+ vec![
+ Value::Int(inst.id),
+ Value::String(inst.name),
+ Value::Bytes(inst.data),
+ ]
+ .into()
+ }
+}
+
+impl From<Record> for Inst {
+ fn from(record: Record) -> Self {
+ let mut it = record.into_iter();
+ Inst {
+ id: match it.next().unwrap() {
+ Value::Int(id) => id,
+ _ => panic!("Expected Int"),
+ },
+ name: match it.next().unwrap() {
+ Value::String(name) => name,
+ _ => panic!("Expected String"),
+ },
+ data: match it.next().unwrap() {
+ Value::Bytes(data) => data,
+ _ => panic!("Expected Bytes"),
+ },
+ }
+ }
+}
+
+impl Inst {
+ pub fn fields() -> Vec<Field> {
+ vec![Field::Id, Field::Name, Field::Data]
+ }
+ pub fn primary_key() -> Field {
+ Field::Id
+ }
+ pub fn secondary_keys() -> Vec<Field> {
+ vec![Field::Name]
+ }
+}
+
+// Function to generate a random integer
+pub fn random_int(from: i64, to: i64) -> i64 {
+ let mut rng = rand::thread_rng();
+ rng.gen_range(from..to)
+}
+
+// Function to generate a random string
+pub fn random_string(len: usize) -> String {
+ let mut rng = rand::thread_rng();
+ (0..len).map(|_| rng.sample(Alphanumeric) as char).collect()
+}
+
+// Function to generate random bytes
+pub fn random_bytes(len: usize) -> Vec<u8> {
+ let mut rng = rand::thread_rng();
+ (0..len).map(|_| rng.gen()).collect()
+}
+
+// Function to generate a random Inst
+pub fn random_inst(from_id: i64, to_id: i64) -> Inst {
+ Inst {
+ id: random_int(from_id, to_id), // Random int value between 0..1000
+ name: random_string(5), // Random string of length 5
+ data: random_bytes(10), // Random bytes of length 10
+ }
+}
+
+pub fn prefill_db(
+ db: &mut DB,
+ insts: &mut Vec<Inst>,
+ n_records: usize,
+ compact: bool,
+) -> DBResult<()> {
+ for i in 0..(n_records - insts.len()) {
+ let inst = random_inst(0, n_records as i64);
+ insts.push(inst.clone());
+ db.upsert(inst)?;
+ if i % 1000 == 0 && compact {
+ db.do_maintenance_tasks()?;
+ }
+ }
+
+ Ok(())
+}