mirror of
https://github.com/RGBCube/dix
synced 2025-07-27 03:37:45 +00:00
performance: perform setup using pragmas on connection creation, set memory-mapped I/O limit high to avoid page faults
This commit is contained in:
parent
646efcf351
commit
7aa726c056
1 changed files with 43 additions and 16 deletions
59
src/store.rs
59
src/store.rs
|
@ -1,32 +1,59 @@
|
||||||
use std::{
|
use std::{collections::HashMap, path::Path, result};
|
||||||
collections::HashMap,
|
|
||||||
path::Path,
|
|
||||||
result,
|
|
||||||
};
|
|
||||||
|
|
||||||
use anyhow::{
|
use anyhow::{Context as _, Result, anyhow};
|
||||||
Context as _,
|
|
||||||
Result,
|
|
||||||
anyhow,
|
|
||||||
};
|
|
||||||
use derive_more::Deref;
|
use derive_more::Deref;
|
||||||
|
use rusqlite::OpenFlags;
|
||||||
|
|
||||||
use crate::{
|
use crate::{DerivationId, StorePath};
|
||||||
DerivationId,
|
|
||||||
StorePath,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Deref)]
|
#[derive(Deref)]
|
||||||
pub struct Connection(rusqlite::Connection);
|
pub struct Connection(rusqlite::Connection);
|
||||||
|
|
||||||
/// Connects to the Nix database.
|
/// Connects to the Nix database
|
||||||
|
///
|
||||||
|
/// and sets some basic settings
|
||||||
pub fn connect() -> Result<Connection> {
|
pub fn connect() -> Result<Connection> {
|
||||||
const DATABASE_PATH: &str = "/nix/var/nix/db/db.sqlite";
|
const DATABASE_PATH: &str = "/nix/var/nix/db/db.sqlite";
|
||||||
|
|
||||||
let inner = rusqlite::Connection::open(DATABASE_PATH).with_context(|| {
|
let inner = rusqlite::Connection::open_with_flags(
|
||||||
|
DATABASE_PATH,
|
||||||
|
OpenFlags::SQLITE_OPEN_READ_ONLY // we only run queries, safeguard against corrupting the ddb
|
||||||
|
| OpenFlags::SQLITE_OPEN_NO_MUTEX // part of the default flags, rusqlite takes care of locking anyways
|
||||||
|
| OpenFlags::SQLITE_OPEN_URI,
|
||||||
|
)
|
||||||
|
.with_context(|| {
|
||||||
format!("failed to connect to Nix database at {DATABASE_PATH}")
|
format!("failed to connect to Nix database at {DATABASE_PATH}")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// perform a batched query to set some settings using PRAGMA
|
||||||
|
// the main performance bottleneck when dix was run before
|
||||||
|
// was that the database file has to be brought from disk into
|
||||||
|
// memory
|
||||||
|
//
|
||||||
|
// We read a large part of the DB anyways in each query,
|
||||||
|
// so it makes sense to set aside a large region of memory-mapped
|
||||||
|
// I/O prevent incuring page faults which can be done using
|
||||||
|
// `mmap_size`
|
||||||
|
//
|
||||||
|
// This made a performance difference of about 500ms (but only
|
||||||
|
// when it was first run!)
|
||||||
|
//
|
||||||
|
// The file pages of the store can be evicted from main memory
|
||||||
|
// using `dd of=/nix/var/nix/db/db.sqlite oflag=nocache conv=notrunc,fdatasync count=0`
|
||||||
|
// if you want to test this. (Source: [https://unix.stackexchange.com/questions/36907/drop-a-specific-file-from-the-linux-filesystem-cache])
|
||||||
|
//
|
||||||
|
// Documentation about the settings can be found [here](https://www.sqlite.org/pragma.html)
|
||||||
|
inner
|
||||||
|
.execute_batch(
|
||||||
|
"
|
||||||
|
PRAGMA mmap_size=268435456; -- 256MB, enough to fit the whole DB (at least on my system)
|
||||||
|
PRAGMA temp_store=2; -- store temporary tables always in memory
|
||||||
|
PRAGMA query_only;",
|
||||||
|
)
|
||||||
|
.with_context(|| {
|
||||||
|
format!("Error during setup commansd of Nix databse as {DATABASE_PATH}")
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(Connection(inner))
|
Ok(Connection(inner))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue