Skip to content

Commit f350d27

Browse files
committed
Add opt-in mimalloc memory allocator
- Add mimalloc feature to nautilus-pyo3, enabled for Python wheels - Set mimalloc as the global allocator in the nautilus CLI binary - Document allocator in README, architecture and Rust guides - Add cargo-vet exemptions for mimalloc crates - Resolves #4358
1 parent 900cfcd commit f350d27

12 files changed

Lines changed: 88 additions & 1 deletion

File tree

.supply-chain/config.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,10 @@ criteria = "safe-to-deploy"
15911591
version = "0.2.16"
15921592
criteria = "safe-to-deploy"
15931593

1594+
[[exemptions.libmimalloc-sys]]
1595+
version = "0.1.49"
1596+
criteria = "safe-to-deploy"
1597+
15941598
[[exemptions.libsqlite3-sys]]
15951599
version = "0.37.0"
15961600
criteria = "safe-to-deploy"
@@ -1655,6 +1659,10 @@ criteria = "safe-to-deploy"
16551659
version = "2.8.2"
16561660
criteria = "safe-to-deploy"
16571661

1662+
[[exemptions.mimalloc]]
1663+
version = "0.1.52"
1664+
criteria = "safe-to-deploy"
1665+
16581666
[[exemptions.mime]]
16591667
version = "0.3.17"
16601668
criteria = "safe-to-deploy"

Cargo.lock

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ log = { version = "0.4.33", features = [
187187
"release_max_level_debug",
188188
] }
189189
madsim = "0.2.34"
190+
mimalloc = "0.1.52"
190191
object_store = { version = "0.13.2", default-features = false, features = [
191192
"fs",
192193
] }

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ DEX), traditional markets (FX, equities, futures, options), and betting exchange
5151

5252
## Features
5353

54-
- **Fast**: Rust core with asynchronous networking using [tokio](https://crates.io/crates/tokio).
54+
- **Fast**: Rust core with the [mimalloc](https://github.com/microsoft/mimalloc) allocator and asynchronous networking using [tokio](https://crates.io/crates/tokio).
5555
- **Reliable**: Type- and thread-safety backed by Rust, with optional Redis-backed state persistence.
5656
- **Portable**: Runs on Linux, macOS, and Windows. Deploy using Docker.
5757
- **Flexible**: Modular adapters integrate any REST API or WebSocket feed.

RELEASES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ installation. Follow-up `2.0.0rcN` wheels are likely to ship at a higher cadence
2424
releases as feedback arrives, before the final `2.0.0` release.
2525

2626
### Enhancements
27+
- Added opt-in `mimalloc` allocator feature, enabled by default for Python wheels (#4358), thanks @ivannp
2728
- Added `LiveNode` metrics for Rust live runner metrics
2829
- Added returns skewness and kurtosis portfolio statistics (#4334), thanks @Martingale42
2930
- Added WebSocket transport backend selection for Python and PyO3 configs (#4342), thanks @graceyangfan

crates/cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ anyhow = { workspace = true }
3838
clap = { workspace = true }
3939
dotenvy = { workspace = true }
4040
log = { workspace = true }
41+
mimalloc = { workspace = true }
4142
serde_json = { workspace = true }
4243
tokio = { workspace = true }
4344
tokio-util = { workspace = true }

crates/cli/src/bin/cli.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@
1818
use std::process::ExitCode;
1919

2020
use clap::FromArgMatches;
21+
use mimalloc::MiMalloc;
2122
use nautilus_cli::opt::NautilusCli;
2223
use nautilus_common::logging::ensure_logging_initialized;
2324

25+
#[global_allocator]
26+
static GLOBAL: MiMalloc = MiMalloc;
27+
2428
#[tokio::main]
2529
async fn main() -> ExitCode {
2630
dotenvy::dotenv().ok();

crates/pyo3/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ high-precision = [
101101
"nautilus-tardis/high-precision",
102102
]
103103
hypersync = ["defi", "nautilus-blockchain/hypersync"]
104+
mimalloc = ["dep:mimalloc"]
104105
postgres = ["nautilus-infrastructure/postgres"]
105106
redis = ["nautilus-infrastructure/redis"]
106107
tracing-bridge = ["nautilus-common/tracing-bridge"]
@@ -159,6 +160,10 @@ nautilus-polymarket = { workspace = true, features = ["python"] }
159160
nautilus-sandbox = { workspace = true, features = ["python"] }
160161
nautilus-tardis = { workspace = true, features = ["python", "replay"] }
161162

163+
# local_dynamic_tls avoids exhausting static TLS space when the extension is dlopen'd
164+
mimalloc = { workspace = true, features = [
165+
"local_dynamic_tls",
166+
], optional = true }
162167
pyo3 = { workspace = true }
163168
pyo3-stub-gen = { workspace = true }
164169

crates/pyo3/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
//! - `hypersync`: Enables hypersync support (fast parallel hash maps) where available.
4242
//! - `tracing-bridge`: Enables the `tracing` subscriber bridge for log integration.
4343
//! - `defi`: Enables DeFi (Decentralized Finance) support including blockchain adapters.
44+
//! - `mimalloc`: Sets [mimalloc](https://github.com/microsoft/mimalloc) as Rust's global allocator (enabled for binary wheels).
4445
4546
#![warn(rustc::all)]
4647
#![deny(unsafe_code)]
@@ -53,9 +54,15 @@
5354

5455
use std::{path::Path, time::Duration};
5556

57+
#[cfg(feature = "mimalloc")]
58+
use mimalloc::MiMalloc;
5659
use nautilus_common::live::runtime::shutdown_runtime;
5760
use pyo3::{prelude::*, pyfunction};
5861

62+
#[cfg(feature = "mimalloc")]
63+
#[global_allocator]
64+
static GLOBAL: MiMalloc = MiMalloc;
65+
5966
const RUNTIME_SHUTDOWN_TIMEOUT_SECS: u64 = 10;
6067

6168
#[pyfunction]

docs/concepts/architecture.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,23 @@ For production deployments, add multiple strategies to a **single TradingNode**
708708
For parallel execution or workload isolation, run each node in its own separate process.
709709
:::
710710

711+
### Memory allocation
712+
713+
The event-driven core allocates and frees small objects at high frequency: message bus dispatch,
714+
order event handling, and order book maintenance all exercise the heap on every event. Default
715+
system allocators handle this pattern poorly; profiling shows allocator overhead approaching half
716+
of hot-loop time on both the Windows CRT heap and glibc malloc under order-flow workloads.
717+
718+
The Python wheels and the `nautilus` CLI binary therefore use
719+
[mimalloc](https://github.com/microsoft/mimalloc) for Rust allocations.
720+
Backtest engine benchmarks run roughly 3% to 44% faster depending on workload,
721+
with order-flow heavy paths gaining the most. The trade-off is a modest increase in resident
722+
memory from mimalloc's segment caching.
723+
724+
A Rust binary links exactly one global allocator, and libraries do not impose one, so the
725+
NautilusTrader crates remain allocator-neutral. When building directly against the crates,
726+
opt in from your own binary (see the [Rust guide](rust.md#memory-allocator)).
727+
711728
## Related guides
712729

713730
- [Overview](overview.md) - High-level introduction to NautilusTrader.

0 commit comments

Comments
 (0)