From 932f3945b1774aca0cd8cce0f7cb7d9ce6b05d56 Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Mon, 20 Apr 2026 11:44:06 +0200 Subject: [PATCH 01/15] perf(db): disable SQLite memory accounting --- Cargo.lock | 1 + crates/db/Cargo.toml | 1 + crates/db/src/init.rs | 29 +++++++++++++++++++++++++++++ crates/db/src/lib.rs | 2 ++ 4 files changed, 33 insertions(+) create mode 100644 crates/db/src/init.rs diff --git a/Cargo.lock b/Cargo.lock index 006e46f007..7f0a0811af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3227,6 +3227,7 @@ dependencies = [ "deadpool-diesel", "deadpool-sync", "diesel", + "libsqlite3-sys", "miden-protocol", "thiserror 2.0.18", "tracing", diff --git a/crates/db/Cargo.toml b/crates/db/Cargo.toml index 2a42af4305..64b24cfcf1 100644 --- a/crates/db/Cargo.toml +++ b/crates/db/Cargo.toml @@ -18,6 +18,7 @@ deadpool = { default-features = false, workspace = true } deadpool-diesel = { features = ["sqlite"], workspace = true } deadpool-sync = { default-features = false, workspace = true } diesel = { features = ["sqlite"], workspace = true } +libsqlite3-sys = { workspace = true } miden-protocol = { workspace = true } thiserror = { workspace = true } tracing = { workspace = true } diff --git a/crates/db/src/init.rs b/crates/db/src/init.rs new file mode 100644 index 0000000000..ef82b0bb50 --- /dev/null +++ b/crates/db/src/init.rs @@ -0,0 +1,29 @@ +use std::sync::Once; + +static INIT: Once = Once::new(); + +/// Initialize SQLite configuration. +/// +/// SQLite has a global configuration that must be initialized before any other SQLite operations. +pub(super) fn initialize_sqlite_configuration() { + INIT.call_once(|| { + disable_sqlite_memory_accounting(); + }); +} + +/// Disables the collection of memory allocation statistics. +/// +/// Some of our queries through Diesel are not cacheable, causing SQLite re-parsing the actual +/// queries on each and every invocation. This in turn results in a large number of memory +/// allocations performed via SQLite's malloc wrapper. +/// +/// Having memory allocation statistics makes SQLite serialize all allocations through a global +/// mutex, which in turn results in significant lock contention. +/// +/// According to the [documentation](https://sqlite.org/c3ref/c_config_covering_index_scan.html) +/// the only thing we lose is access to memory allocation statistics -- we don't use that. +fn disable_sqlite_memory_accounting() { + let result = + unsafe { libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_MEMSTATUS, 0) }; + assert!(result == libsqlite3_sys::SQLITE_OK); +} diff --git a/crates/db/src/lib.rs b/crates/db/src/lib.rs index 7000f131d1..d7c6d27aca 100644 --- a/crates/db/src/lib.rs +++ b/crates/db/src/lib.rs @@ -1,5 +1,6 @@ mod conv; mod errors; +mod init; mod manager; use std::path::Path; @@ -22,6 +23,7 @@ pub struct Db { impl Db { /// Creates a new database instance with the provided connection pool. pub fn new(database_filepath: &Path) -> Result { + init::initialize_sqlite_configuration(); let manager = ConnectionManager::new(database_filepath.to_str().unwrap()); let pool = deadpool_diesel::Pool::builder(manager).max_size(16).build()?; Ok(Self { pool }) From 24bf938e547b4ca92d6b89afdca53afe9ffead29 Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Thu, 23 Apr 2026 10:31:00 +0200 Subject: [PATCH 02/15] fix(db): make SQLite initialization public Some places are creating SQLiteConnections directly so we have to explicitly call the initialization function there. --- crates/db/src/init.rs | 3 ++- crates/db/src/lib.rs | 3 ++- crates/ntx-builder/src/db/mod.rs | 3 ++- crates/store/src/db/mod.rs | 3 +++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/db/src/init.rs b/crates/db/src/init.rs index ef82b0bb50..805b9bd1f7 100644 --- a/crates/db/src/init.rs +++ b/crates/db/src/init.rs @@ -5,7 +5,7 @@ static INIT: Once = Once::new(); /// Initialize SQLite configuration. /// /// SQLite has a global configuration that must be initialized before any other SQLite operations. -pub(super) fn initialize_sqlite_configuration() { +pub fn initialize_sqlite_configuration() { INIT.call_once(|| { disable_sqlite_memory_accounting(); }); @@ -25,5 +25,6 @@ pub(super) fn initialize_sqlite_configuration() { fn disable_sqlite_memory_accounting() { let result = unsafe { libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_MEMSTATUS, 0) }; + // assert!((result == libsqlite3_sys::SQLITE_OK) || (result == libsqlite3_sys::SQLITE_MISUSE)); assert!(result == libsqlite3_sys::SQLITE_OK); } diff --git a/crates/db/src/lib.rs b/crates/db/src/lib.rs index d7c6d27aca..8d0ee53e14 100644 --- a/crates/db/src/lib.rs +++ b/crates/db/src/lib.rs @@ -8,6 +8,7 @@ use std::path::Path; pub use conv::{DatabaseTypeConversionError, SqlTypeConvert}; use diesel::{RunQueryDsl, SqliteConnection}; pub use errors::{DatabaseError, SchemaVerificationError}; +pub use init::initialize_sqlite_configuration; pub use manager::{ConnectionManager, ConnectionManagerError, configure_connection_on_creation}; use tracing::Instrument; @@ -23,7 +24,7 @@ pub struct Db { impl Db { /// Creates a new database instance with the provided connection pool. pub fn new(database_filepath: &Path) -> Result { - init::initialize_sqlite_configuration(); + initialize_sqlite_configuration(); let manager = ConnectionManager::new(database_filepath.to_str().unwrap()); let pool = deadpool_diesel::Pool::builder(manager).max_size(16).build()?; Ok(Self { pool }) diff --git a/crates/ntx-builder/src/db/mod.rs b/crates/ntx-builder/src/db/mod.rs index 28f1fef933..c1c69d22c9 100644 --- a/crates/ntx-builder/src/db/mod.rs +++ b/crates/ntx-builder/src/db/mod.rs @@ -225,10 +225,11 @@ impl Db { #[cfg(test)] pub fn test_conn() -> (diesel::SqliteConnection, tempfile::TempDir) { use diesel::{Connection, SqliteConnection}; - use miden_node_db::configure_connection_on_creation; + use miden_node_db::{configure_connection_on_creation, initialize_sqlite_configuration}; let dir = tempfile::tempdir().expect("failed to create temp directory"); let db_path = dir.path().join("test.sqlite3"); + initialize_sqlite_configuration(); let mut conn = SqliteConnection::establish(db_path.to_str().unwrap()) .expect("temp file sqlite should always work"); configure_connection_on_creation(&mut conn).expect("connection configuration should work"); diff --git a/crates/store/src/db/mod.rs b/crates/store/src/db/mod.rs index 86581a9d96..2ab40b60bd 100644 --- a/crates/store/src/db/mod.rs +++ b/crates/store/src/db/mod.rs @@ -256,6 +256,9 @@ impl Db { err, )] pub fn bootstrap(database_filepath: PathBuf, genesis: GenesisBlock) -> anyhow::Result<()> { + // Initialize SQLite configuration _before_ creating a connection. + miden_node_db::initialize_sqlite_configuration(); + // Create database. // // This will create the file if it does not exist, but will also happily open it if already From 7911adc85b08bcf33d8d110e8ac1d93ba0c4de4c Mon Sep 17 00:00:00 2001 From: KOVACS Krisztian Date: Thu, 23 Apr 2026 10:37:24 +0200 Subject: [PATCH 03/15] Update crates/db/src/init.rs Co-authored-by: Mirko <48352201+Mirko-von-Leipzig@users.noreply.github.com> --- crates/db/src/init.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db/src/init.rs b/crates/db/src/init.rs index 805b9bd1f7..e539c7c8be 100644 --- a/crates/db/src/init.rs +++ b/crates/db/src/init.rs @@ -26,5 +26,5 @@ fn disable_sqlite_memory_accounting() { let result = unsafe { libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_MEMSTATUS, 0) }; // assert!((result == libsqlite3_sys::SQLITE_OK) || (result == libsqlite3_sys::SQLITE_MISUSE)); - assert!(result == libsqlite3_sys::SQLITE_OK); + assert_eq!(result, libsqlite3_sys::SQLITE_OK); } From 0d17a179446e1f6e34efcc74218cfaf5eb7e2234 Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Thu, 23 Apr 2026 10:45:07 +0200 Subject: [PATCH 04/15] fix: add SAFETY comment --- crates/db/src/init.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/db/src/init.rs b/crates/db/src/init.rs index e539c7c8be..e4c470ece3 100644 --- a/crates/db/src/init.rs +++ b/crates/db/src/init.rs @@ -23,8 +23,10 @@ pub fn initialize_sqlite_configuration() { /// According to the [documentation](https://sqlite.org/c3ref/c_config_covering_index_scan.html) /// the only thing we lose is access to memory allocation statistics -- we don't use that. fn disable_sqlite_memory_accounting() { + // SAFETY: `sqlite3_config` is called at most once through `INIT.call_once` during process + // initialization. Calling this _after_ performing SQLite operations results is considered + // a programming error and results in a panic. let result = unsafe { libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_MEMSTATUS, 0) }; - // assert!((result == libsqlite3_sys::SQLITE_OK) || (result == libsqlite3_sys::SQLITE_MISUSE)); assert_eq!(result, libsqlite3_sys::SQLITE_OK); } From 063e3b7eb0099240114b9199b385e8f6affe1138 Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Fri, 24 Apr 2026 09:38:33 +0200 Subject: [PATCH 05/15] Revert "fix: add SAFETY comment" This reverts commit 0d17a179446e1f6e34efcc74218cfaf5eb7e2234. --- crates/db/src/init.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/db/src/init.rs b/crates/db/src/init.rs index e4c470ece3..e539c7c8be 100644 --- a/crates/db/src/init.rs +++ b/crates/db/src/init.rs @@ -23,10 +23,8 @@ pub fn initialize_sqlite_configuration() { /// According to the [documentation](https://sqlite.org/c3ref/c_config_covering_index_scan.html) /// the only thing we lose is access to memory allocation statistics -- we don't use that. fn disable_sqlite_memory_accounting() { - // SAFETY: `sqlite3_config` is called at most once through `INIT.call_once` during process - // initialization. Calling this _after_ performing SQLite operations results is considered - // a programming error and results in a panic. let result = unsafe { libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_MEMSTATUS, 0) }; + // assert!((result == libsqlite3_sys::SQLITE_OK) || (result == libsqlite3_sys::SQLITE_MISUSE)); assert_eq!(result, libsqlite3_sys::SQLITE_OK); } From 6d2e7c30f86569fc4c930aa4f8a31b592ba16f12 Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Fri, 24 Apr 2026 09:38:41 +0200 Subject: [PATCH 06/15] Revert "Update crates/db/src/init.rs" This reverts commit 7911adc85b08bcf33d8d110e8ac1d93ba0c4de4c. --- crates/db/src/init.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db/src/init.rs b/crates/db/src/init.rs index e539c7c8be..805b9bd1f7 100644 --- a/crates/db/src/init.rs +++ b/crates/db/src/init.rs @@ -26,5 +26,5 @@ fn disable_sqlite_memory_accounting() { let result = unsafe { libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_MEMSTATUS, 0) }; // assert!((result == libsqlite3_sys::SQLITE_OK) || (result == libsqlite3_sys::SQLITE_MISUSE)); - assert_eq!(result, libsqlite3_sys::SQLITE_OK); + assert!(result == libsqlite3_sys::SQLITE_OK); } From 64e1e62253a256e0b0441ae3a3fd2e443831a32e Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Fri, 24 Apr 2026 09:38:49 +0200 Subject: [PATCH 07/15] Revert "fix(db): make SQLite initialization public" This reverts commit 24bf938e547b4ca92d6b89afdca53afe9ffead29. --- crates/db/src/init.rs | 3 +-- crates/db/src/lib.rs | 3 +-- crates/ntx-builder/src/db/mod.rs | 3 +-- crates/store/src/db/mod.rs | 3 --- 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/crates/db/src/init.rs b/crates/db/src/init.rs index 805b9bd1f7..ef82b0bb50 100644 --- a/crates/db/src/init.rs +++ b/crates/db/src/init.rs @@ -5,7 +5,7 @@ static INIT: Once = Once::new(); /// Initialize SQLite configuration. /// /// SQLite has a global configuration that must be initialized before any other SQLite operations. -pub fn initialize_sqlite_configuration() { +pub(super) fn initialize_sqlite_configuration() { INIT.call_once(|| { disable_sqlite_memory_accounting(); }); @@ -25,6 +25,5 @@ pub fn initialize_sqlite_configuration() { fn disable_sqlite_memory_accounting() { let result = unsafe { libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_MEMSTATUS, 0) }; - // assert!((result == libsqlite3_sys::SQLITE_OK) || (result == libsqlite3_sys::SQLITE_MISUSE)); assert!(result == libsqlite3_sys::SQLITE_OK); } diff --git a/crates/db/src/lib.rs b/crates/db/src/lib.rs index 8d0ee53e14..d7c6d27aca 100644 --- a/crates/db/src/lib.rs +++ b/crates/db/src/lib.rs @@ -8,7 +8,6 @@ use std::path::Path; pub use conv::{DatabaseTypeConversionError, SqlTypeConvert}; use diesel::{RunQueryDsl, SqliteConnection}; pub use errors::{DatabaseError, SchemaVerificationError}; -pub use init::initialize_sqlite_configuration; pub use manager::{ConnectionManager, ConnectionManagerError, configure_connection_on_creation}; use tracing::Instrument; @@ -24,7 +23,7 @@ pub struct Db { impl Db { /// Creates a new database instance with the provided connection pool. pub fn new(database_filepath: &Path) -> Result { - initialize_sqlite_configuration(); + init::initialize_sqlite_configuration(); let manager = ConnectionManager::new(database_filepath.to_str().unwrap()); let pool = deadpool_diesel::Pool::builder(manager).max_size(16).build()?; Ok(Self { pool }) diff --git a/crates/ntx-builder/src/db/mod.rs b/crates/ntx-builder/src/db/mod.rs index c1c69d22c9..28f1fef933 100644 --- a/crates/ntx-builder/src/db/mod.rs +++ b/crates/ntx-builder/src/db/mod.rs @@ -225,11 +225,10 @@ impl Db { #[cfg(test)] pub fn test_conn() -> (diesel::SqliteConnection, tempfile::TempDir) { use diesel::{Connection, SqliteConnection}; - use miden_node_db::{configure_connection_on_creation, initialize_sqlite_configuration}; + use miden_node_db::configure_connection_on_creation; let dir = tempfile::tempdir().expect("failed to create temp directory"); let db_path = dir.path().join("test.sqlite3"); - initialize_sqlite_configuration(); let mut conn = SqliteConnection::establish(db_path.to_str().unwrap()) .expect("temp file sqlite should always work"); configure_connection_on_creation(&mut conn).expect("connection configuration should work"); diff --git a/crates/store/src/db/mod.rs b/crates/store/src/db/mod.rs index 2ab40b60bd..86581a9d96 100644 --- a/crates/store/src/db/mod.rs +++ b/crates/store/src/db/mod.rs @@ -256,9 +256,6 @@ impl Db { err, )] pub fn bootstrap(database_filepath: PathBuf, genesis: GenesisBlock) -> anyhow::Result<()> { - // Initialize SQLite configuration _before_ creating a connection. - miden_node_db::initialize_sqlite_configuration(); - // Create database. // // This will create the file if it does not exist, but will also happily open it if already From b9732b536d078f2c5b7c6c1695ba65e3c4a753d2 Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Fri, 24 Apr 2026 09:38:56 +0200 Subject: [PATCH 08/15] Revert "perf(db): disable SQLite memory accounting" This reverts commit 932f3945b1774aca0cd8cce0f7cb7d9ce6b05d56. --- Cargo.lock | 1 - crates/db/Cargo.toml | 1 - crates/db/src/init.rs | 29 ----------------------------- crates/db/src/lib.rs | 2 -- 4 files changed, 33 deletions(-) delete mode 100644 crates/db/src/init.rs diff --git a/Cargo.lock b/Cargo.lock index 7f0a0811af..006e46f007 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3227,7 +3227,6 @@ dependencies = [ "deadpool-diesel", "deadpool-sync", "diesel", - "libsqlite3-sys", "miden-protocol", "thiserror 2.0.18", "tracing", diff --git a/crates/db/Cargo.toml b/crates/db/Cargo.toml index 64b24cfcf1..2a42af4305 100644 --- a/crates/db/Cargo.toml +++ b/crates/db/Cargo.toml @@ -18,7 +18,6 @@ deadpool = { default-features = false, workspace = true } deadpool-diesel = { features = ["sqlite"], workspace = true } deadpool-sync = { default-features = false, workspace = true } diesel = { features = ["sqlite"], workspace = true } -libsqlite3-sys = { workspace = true } miden-protocol = { workspace = true } thiserror = { workspace = true } tracing = { workspace = true } diff --git a/crates/db/src/init.rs b/crates/db/src/init.rs deleted file mode 100644 index ef82b0bb50..0000000000 --- a/crates/db/src/init.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::sync::Once; - -static INIT: Once = Once::new(); - -/// Initialize SQLite configuration. -/// -/// SQLite has a global configuration that must be initialized before any other SQLite operations. -pub(super) fn initialize_sqlite_configuration() { - INIT.call_once(|| { - disable_sqlite_memory_accounting(); - }); -} - -/// Disables the collection of memory allocation statistics. -/// -/// Some of our queries through Diesel are not cacheable, causing SQLite re-parsing the actual -/// queries on each and every invocation. This in turn results in a large number of memory -/// allocations performed via SQLite's malloc wrapper. -/// -/// Having memory allocation statistics makes SQLite serialize all allocations through a global -/// mutex, which in turn results in significant lock contention. -/// -/// According to the [documentation](https://sqlite.org/c3ref/c_config_covering_index_scan.html) -/// the only thing we lose is access to memory allocation statistics -- we don't use that. -fn disable_sqlite_memory_accounting() { - let result = - unsafe { libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_MEMSTATUS, 0) }; - assert!(result == libsqlite3_sys::SQLITE_OK); -} diff --git a/crates/db/src/lib.rs b/crates/db/src/lib.rs index d7c6d27aca..7000f131d1 100644 --- a/crates/db/src/lib.rs +++ b/crates/db/src/lib.rs @@ -1,6 +1,5 @@ mod conv; mod errors; -mod init; mod manager; use std::path::Path; @@ -23,7 +22,6 @@ pub struct Db { impl Db { /// Creates a new database instance with the provided connection pool. pub fn new(database_filepath: &Path) -> Result { - init::initialize_sqlite_configuration(); let manager = ConnectionManager::new(database_filepath.to_str().unwrap()); let pool = deadpool_diesel::Pool::builder(manager).max_size(16).build()?; Ok(Self { pool }) From 43d080a75864970f565c02a5bb0cc522428807dc Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Thu, 23 Apr 2026 14:22:09 +0200 Subject: [PATCH 09/15] perf(node): disable SQLite memory management for the Docker build --- bin/node/Dockerfile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bin/node/Dockerfile b/bin/node/Dockerfile index 04cb6783cd..1ca9a2bb99 100644 --- a/bin/node/Dockerfile +++ b/bin/node/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && \ cmake \ pkg-config \ libssl-dev \ - libsqlite3-dev \ ca-certificates && \ rm -rf /var/lib/apt/lists/* RUN cargo install cargo-chef @@ -21,6 +20,7 @@ RUN cargo chef prepare --recipe-path recipe.json FROM chef AS builder COPY --from=planner /app/recipe.json recipe.json +ENV LIBSQLITE3_FLAGS="-USQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_DEFAULT_MEMSTATUS=0" # Build dependencies - this is the caching Docker layer! RUN cargo chef cook --release --recipe-path recipe.json # Build application @@ -31,8 +31,7 @@ RUN cargo build --release --locked --bin miden-node FROM debian:bullseye-slim AS runtime-base RUN apt-get update && \ apt-get -y upgrade && \ - apt-get install -y --no-install-recommends sqlite3 \ - && rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/* FROM runtime-base AS runtime COPY --from=builder /app/target/release/miden-node /usr/local/bin/miden-node @@ -52,4 +51,4 @@ LABEL org.opencontainers.image.created=$CREATED \ # Expose RPC port EXPOSE 57291 # Miden node does not spawn sub-processes, so it can be used as the PID1 -CMD miden-node +CMD ["miden-node"] From 47dea688c8fa800bd56e577c23b0d1c225563196 Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Fri, 24 Apr 2026 09:56:45 +0200 Subject: [PATCH 10/15] perf: set compile-time flags in Makefile --- Makefile | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 33ab72a885..d997a58db5 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,10 @@ help: WARNINGS=RUSTDOCFLAGS="-D warnings" CONTAINER_RUNTIME ?= docker STRESS_TEST_DATA_DIR ?= stress-test-store-$(shell date +%Y%m%d-%H%M%S) +# These compile-time flags are used to disable SQLite's memory accounting features. These introduce global mutexes +# into SQLite's memory allocator which can cause contention and performance degradation in high-concurrency scenarios +# we have in the node. +LIBSQLITE3_FLAGS ?= "-USQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_DEFAULT_MEMSTATUS=0" # -- linting -------------------------------------------------------------------------------------- @@ -102,24 +106,25 @@ build: ## Builds all crates and re-builds protobuf bindings for proto crates .PHONY: install-node install-node: ## Installs node - cargo install --path bin/node --locked + LIBSQLITE3_FLAGS=$(LIBSQLITE3_FLAGS) cargo install --path bin/node --locked .PHONY: install-remote-prover install-remote-prover: ## Install remote prover's CLI cargo install --path bin/remote-prover --bin miden-remote-prover --locked -.PHONY: stress-test-smoke +.PHONY: stress-test stress-test: ## Runs stress-test benchmarks - cargo build --release --locked -p miden-node-stress-test + LIBSQLITE3_FLAGS=$(LIBSQLITE3_FLAGS) cargo build --release --locked -p miden-node-stress-test @mkdir -p $(STRESS_TEST_DATA_DIR) ./target/release/miden-node-stress-test seed-store --data-directory $(STRESS_TEST_DATA_DIR) --num-accounts 500 --public-accounts-percentage 50 - ./target/release/miden-node-stress-test benchmark-store --data-directory $(STRESS_TEST_DATA_DIR) --iterations 10 --concurrency 1 sync-state ./target/release/miden-node-stress-test benchmark-store --data-directory $(STRESS_TEST_DATA_DIR) --iterations 10 --concurrency 1 sync-notes ./target/release/miden-node-stress-test benchmark-store --data-directory $(STRESS_TEST_DATA_DIR) --iterations 10 --concurrency 1 sync-nullifiers --prefixes 10 + ./target/release/miden-node-stress-test benchmark-store --data-directory $(STRESS_TEST_DATA_DIR) --iterations 10 --concurrency 1 sync-transactions + ./target/release/miden-node-stress-test benchmark-store --data-directory $(STRESS_TEST_DATA_DIR) --iterations 10 --concurrency 1 sync-chain-mmr .PHONY: install-stress-test install-stress-test: ## Installs stress-test binary - cargo install --path bin/stress-test --locked + LIBSQLITE3_FLAGS=$(LIBSQLITE3_FLAGS) cargo install --path bin/stress-test --locked .PHONY: install-network-monitor install-network-monitor: ## Installs network monitor binary From 35b932994510268e32d5a428fc505dcc000a3881 Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Fri, 24 Apr 2026 10:23:05 +0200 Subject: [PATCH 11/15] fix(docker): use correct runtime-base image Binaries built on Debian `bookworm` won't run on `bullseye`. --- bin/node/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/Dockerfile b/bin/node/Dockerfile index 1ca9a2bb99..b69bd78d93 100644 --- a/bin/node/Dockerfile +++ b/bin/node/Dockerfile @@ -28,7 +28,7 @@ COPY . . RUN cargo build --release --locked --bin miden-node # Base line runtime image with runtime dependencies installed. -FROM debian:bullseye-slim AS runtime-base +FROM debian:bookworm-slim AS runtime-base RUN apt-get update && \ apt-get -y upgrade && \ rm -rf /var/lib/apt/lists/* From 2768b460ab78fe25e4f726cf0975ad348feaca85 Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Fri, 24 Apr 2026 11:06:59 +0200 Subject: [PATCH 12/15] Revert "perf: set compile-time flags in Makefile" This reverts commit 47dea688c8fa800bd56e577c23b0d1c225563196. --- Makefile | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index d997a58db5..33ab72a885 100644 --- a/Makefile +++ b/Makefile @@ -9,10 +9,6 @@ help: WARNINGS=RUSTDOCFLAGS="-D warnings" CONTAINER_RUNTIME ?= docker STRESS_TEST_DATA_DIR ?= stress-test-store-$(shell date +%Y%m%d-%H%M%S) -# These compile-time flags are used to disable SQLite's memory accounting features. These introduce global mutexes -# into SQLite's memory allocator which can cause contention and performance degradation in high-concurrency scenarios -# we have in the node. -LIBSQLITE3_FLAGS ?= "-USQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_DEFAULT_MEMSTATUS=0" # -- linting -------------------------------------------------------------------------------------- @@ -106,25 +102,24 @@ build: ## Builds all crates and re-builds protobuf bindings for proto crates .PHONY: install-node install-node: ## Installs node - LIBSQLITE3_FLAGS=$(LIBSQLITE3_FLAGS) cargo install --path bin/node --locked + cargo install --path bin/node --locked .PHONY: install-remote-prover install-remote-prover: ## Install remote prover's CLI cargo install --path bin/remote-prover --bin miden-remote-prover --locked -.PHONY: stress-test +.PHONY: stress-test-smoke stress-test: ## Runs stress-test benchmarks - LIBSQLITE3_FLAGS=$(LIBSQLITE3_FLAGS) cargo build --release --locked -p miden-node-stress-test + cargo build --release --locked -p miden-node-stress-test @mkdir -p $(STRESS_TEST_DATA_DIR) ./target/release/miden-node-stress-test seed-store --data-directory $(STRESS_TEST_DATA_DIR) --num-accounts 500 --public-accounts-percentage 50 + ./target/release/miden-node-stress-test benchmark-store --data-directory $(STRESS_TEST_DATA_DIR) --iterations 10 --concurrency 1 sync-state ./target/release/miden-node-stress-test benchmark-store --data-directory $(STRESS_TEST_DATA_DIR) --iterations 10 --concurrency 1 sync-notes ./target/release/miden-node-stress-test benchmark-store --data-directory $(STRESS_TEST_DATA_DIR) --iterations 10 --concurrency 1 sync-nullifiers --prefixes 10 - ./target/release/miden-node-stress-test benchmark-store --data-directory $(STRESS_TEST_DATA_DIR) --iterations 10 --concurrency 1 sync-transactions - ./target/release/miden-node-stress-test benchmark-store --data-directory $(STRESS_TEST_DATA_DIR) --iterations 10 --concurrency 1 sync-chain-mmr .PHONY: install-stress-test install-stress-test: ## Installs stress-test binary - LIBSQLITE3_FLAGS=$(LIBSQLITE3_FLAGS) cargo install --path bin/stress-test --locked + cargo install --path bin/stress-test --locked .PHONY: install-network-monitor install-network-monitor: ## Installs network monitor binary From 8bbb6c7a477082ff77c962f71a89749e0f46d892 Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Fri, 24 Apr 2026 11:23:00 +0200 Subject: [PATCH 13/15] Revert "fix(docker): use correct runtime-base image" This reverts commit 35b932994510268e32d5a428fc505dcc000a3881. --- bin/node/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/Dockerfile b/bin/node/Dockerfile index b69bd78d93..1ca9a2bb99 100644 --- a/bin/node/Dockerfile +++ b/bin/node/Dockerfile @@ -28,7 +28,7 @@ COPY . . RUN cargo build --release --locked --bin miden-node # Base line runtime image with runtime dependencies installed. -FROM debian:bookworm-slim AS runtime-base +FROM debian:bullseye-slim AS runtime-base RUN apt-get update && \ apt-get -y upgrade && \ rm -rf /var/lib/apt/lists/* From 6c6271e3472e1a21f68e0b61ae36974b48819bdc Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Fri, 24 Apr 2026 11:23:31 +0200 Subject: [PATCH 14/15] Revert "perf(node): disable SQLite memory management for the Docker build" This reverts commit 43d080a75864970f565c02a5bb0cc522428807dc. --- bin/node/Dockerfile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bin/node/Dockerfile b/bin/node/Dockerfile index 1ca9a2bb99..04cb6783cd 100644 --- a/bin/node/Dockerfile +++ b/bin/node/Dockerfile @@ -9,6 +9,7 @@ RUN apt-get update && \ cmake \ pkg-config \ libssl-dev \ + libsqlite3-dev \ ca-certificates && \ rm -rf /var/lib/apt/lists/* RUN cargo install cargo-chef @@ -20,7 +21,6 @@ RUN cargo chef prepare --recipe-path recipe.json FROM chef AS builder COPY --from=planner /app/recipe.json recipe.json -ENV LIBSQLITE3_FLAGS="-USQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_DEFAULT_MEMSTATUS=0" # Build dependencies - this is the caching Docker layer! RUN cargo chef cook --release --recipe-path recipe.json # Build application @@ -31,7 +31,8 @@ RUN cargo build --release --locked --bin miden-node FROM debian:bullseye-slim AS runtime-base RUN apt-get update && \ apt-get -y upgrade && \ - rm -rf /var/lib/apt/lists/* + apt-get install -y --no-install-recommends sqlite3 \ + && rm -rf /var/lib/apt/lists/* FROM runtime-base AS runtime COPY --from=builder /app/target/release/miden-node /usr/local/bin/miden-node @@ -51,4 +52,4 @@ LABEL org.opencontainers.image.created=$CREATED \ # Expose RPC port EXPOSE 57291 # Miden node does not spawn sub-processes, so it can be used as the PID1 -CMD ["miden-node"] +CMD miden-node From d1872adc46c72d7bd5928846221ff864aaa1b8d6 Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Fri, 24 Apr 2026 11:23:45 +0200 Subject: [PATCH 15/15] perf(cargo): disable SQLite memory accounting --- .cargo/config.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.cargo/config.toml b/.cargo/config.toml index 2e07606d52..003c52b3df 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,9 @@ [target.wasm32-unknown-unknown] rustflags = ['--cfg', 'getrandom_backend="wasm_js"'] + +[env] +# These compile-time flags are used to disable SQLite's memory +# accounting features. These introduce global mutexes into SQLite's +# memory allocator which can cause contention and performance +# degradation in high-concurrency scenarios we have in the node. +LIBSQLITE3_FLAGS = "-USQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_DEFAULT_MEMSTATUS=0"