Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: set MDB_NOLOCK for peer and blockchain database #3473

Merged
4 changes: 3 additions & 1 deletion base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

use croaring::Bitmap;
use fs2::FileExt;
use lmdb_zero::{ConstTransaction, Database, Environment, ReadTransaction, WriteTransaction};
use lmdb_zero::{open, ConstTransaction, Database, Environment, ReadTransaction, WriteTransaction};
use log::*;
use serde::{Deserialize, Serialize};
use std::{fmt, fs, fs::File, ops::Deref, path::Path, sync::Arc, time::Instant};
Expand Down Expand Up @@ -128,6 +128,8 @@ pub fn create_lmdb_database<P: AsRef<Path>>(path: P, config: LMDBConfig) -> Resu

let lmdb_store = LMDBBuilder::new()
.set_path(path)
// NOLOCK - No lock required because we manage the DB locking using a RwLock
.set_env_flags(open::NOLOCK)
.set_env_config(config)
.set_max_number_of_databases(20)
.add_database(LMDB_DB_METADATA, flags | db::INTEGERKEY)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,6 @@ mod fetch_block_hashes_from_header_tip {
}

mod add_block {

use super::*;

#[test]
Expand Down Expand Up @@ -396,10 +395,13 @@ mod add_block {
}]);

let (block, _) = create_next_block(&prev_block, txns);
let err = db.add_block(block).unwrap_err();
let err = db.add_block(block.clone()).unwrap_err();
unpack_enum!(ChainStorageError::KeyExists { key, table_name } = err);
assert_eq!(table_name, "utxo_commitment_index");
assert_eq!(key, prev_output.commitment.to_hex());
// Check rollback
let header = db.fetch_header(block.header.height).unwrap();
assert!(header.is_none());

let (txns, _) = schema_to_transaction(&[txn_schema!(from: vec![prev_utxo.clone()], to: vec![50 * T])]);
let (block, _) = create_next_block(&prev_block, txns);
Expand Down
3 changes: 3 additions & 0 deletions base_layer/p2p/src/initialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use crate::{
};
use fs2::FileExt;
use futures::future;
use lmdb_zero::open;
use log::*;
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use std::{
Expand Down Expand Up @@ -174,6 +175,7 @@ pub async fn initialize_local_test_comms(
std::fs::create_dir_all(data_path).unwrap();
let datastore = LMDBBuilder::new()
.set_path(data_path)
.set_env_flags(open::NOLOCK)
.set_env_config(LMDBConfig::default())
.set_max_number_of_databases(1)
.add_database(&peer_database_name, lmdb_zero::db::CREATE)
Expand Down Expand Up @@ -326,6 +328,7 @@ async fn configure_comms_and_dht(

let datastore = LMDBBuilder::new()
.set_path(&config.datastore_path)
.set_env_flags(open::NOLOCK)
.set_env_config(LMDBConfig::default())
.set_max_number_of_databases(1)
.add_database(&config.peer_database_name, lmdb_zero::db::CREATE)
Expand Down
31 changes: 22 additions & 9 deletions infrastructure/storage/src/lmdb_store/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ impl Default for LMDBConfig {
/// .build()
/// .unwrap();
/// ```
#[derive(Default)]
pub struct LMDBBuilder {
path: PathBuf,
env_flags: open::Flags,
max_dbs: usize,
db_names: HashMap<String, db::Flags>,
env_config: LMDBConfig,
Expand All @@ -124,12 +124,7 @@ impl LMDBBuilder {
/// | path | ./store/|
/// | named DBs | none |
pub fn new() -> LMDBBuilder {
LMDBBuilder {
path: "./store/".into(),
db_names: HashMap::new(),
max_dbs: 8,
env_config: LMDBConfig::default(),
}
Default::default()
}

/// Set the directory where the LMDB database exists, or must be created.
Expand All @@ -140,6 +135,12 @@ impl LMDBBuilder {
self
}

/// Set environment flags
pub fn set_env_flags(mut self, flags: open::Flags) -> LMDBBuilder {
self.env_flags = flags;
self
}

/// Sets the parameters of the LMDB environment.
/// The actual memory will only be allocated when #build() is called
pub fn set_env_config(mut self, config: LMDBConfig) -> LMDBBuilder {
Expand Down Expand Up @@ -174,8 +175,8 @@ impl LMDBBuilder {
let mut builder = EnvBuilder::new()?;
builder.set_mapsize(self.env_config.init_size_bytes)?;
builder.set_maxdbs(max_dbs)?;
// Using open::Flags::NOTLS does not compile!?! NOTLS=0x200000
let flags = open::Flags::from_bits(0x0020_0000).expect("LMDB open::Flag is correct");
// Always include NOTLS flag since we know that we're using this with tokio
let flags = self.env_flags | open::NOTLS;
let env = builder.open(&path, flags, 0o600)?;
// SAFETY: no transactions can be open at this point
LMDBStore::resize_if_required(&env, &self.env_config)?;
Expand Down Expand Up @@ -214,6 +215,18 @@ impl LMDBBuilder {
}
}

impl Default for LMDBBuilder {
fn default() -> Self {
Self {
path: "./store/".into(),
env_flags: open::Flags::empty(),
db_names: HashMap::new(),
max_dbs: 8,
env_config: LMDBConfig::default(),
}
}
}

/// A Struct for holding state for an LM Database. LMDB is memory mapped, so you can treat the DB as an (essentially)
/// infinitely large memory-backed hashmap. A single environment is stored in one file. The individual databases
/// are key-value tables stored within the file.
Expand Down