Release profile optimization, LTO, codegen-units. Memory allocators (jemalloc, mimalloc). Connection pooling, request batching. Scaling strategies, microservices with Rust.
Rust: From Basics to Advanced
Part 6: Testing, CI/CD & Production
xdev.asia
1. Release Profile Optimization
# Cargo.toml
[profile.release]
opt-level = 3 # Maximum optimization
lto = "fat" # Link-Time Optimization — binary nhỏ hơn, nhanh hơn
codegen-units = 1 # Single codegen unit — tối ưu tốt hơn
strip = true # Strip debug symbols
panic = "abort" # Không unwind — binary nhỏ hơn
[profile.dev]
opt-level = 0
debug = true
# Custom profile
[profile.profiling]
inherits = "release"
debug = true # Debug symbols nhưng optimized
strip = false
# Build size comparison
cargo build --release
ls -la target/release/my-app # ~5MB (stripped, LTO)
# Analyze binary size
cargo install cargo-bloat
cargo bloat --release --crates
2. Memory Allocators
// jemalloc — tốt cho multi-threaded workloads
#[global_allocator]
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
// mimalloc — tốt cho general purpose
// [dependencies]
// mimalloc = { version = "0.1", default-features = false }
#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
| Allocator | Use cases | Pros |
| System (default) | General | No extra dependencies |
| jemalloc | High-concurrency servers | Reduce fragmentation and multi-thread |
| mimalloc | General, latency-sensitive | Fast, compact, cross-platform |
// Connection pooling
let pool = PgPoolOptions::new()
.max_connections(20)
.min_connections(5)
.max_lifetime(Duration::from_secs(1800))
.idle_timeout(Duration::from_secs(600))
.acquire_timeout(Duration::from_secs(5))
.connect(&database_url)
.await?;
// Request batching
use tokio::sync::mpsc;
use tokio::time::interval;
struct Batcher {
tx: mpsc::Sender<BatchItem>,
}
impl Batcher {
fn new(pool: PgPool) -> Self {
let (tx, mut rx) = mpsc::channel(1000);
tokio::spawn(async move {
let mut buffer = Vec::new();
let mut tick = interval(Duration::from_millis(100));
loop {
tokio::select! {
Some(item) = rx.recv() => {
buffer.push(item);
if buffer.len() >= 100 {
flush_batch(&pool, &mut buffer).await;
}
}
_ = tick.tick() => {
if !buffer.is_empty() {
flush_batch(&pool, &mut buffer).await;
}
}
}
}
});
Self { tx }
}
}
// String optimization — avoid allocation
fn process(input: &str) -> &str {
// Trả reference thay vì clone
input.trim()
}
// Cow — clone on write
use std::borrow::Cow;
fn normalize(input: &str) -> Cow<'_, str> {
if input.contains(' ') {
Cow::Owned(input.replace(' ', "_"))
} else {
Cow::Borrowed(input)
}
}
4. Production Checklist
| Category | Item |
| Build | LTO enabled, single codegen-unit, stripped |
| Allocator | jemalloc or mimalloc |
| Logging | tracing + JSON format + RUST_LOG |
| Metrics | Prometheus + Grafana |
| Health | /health endpoint, readiness/liveness |
| Shut down | Graceful shutdown (SIGTERM) |
| Security | cargo audit, cargo deny |
| Docker | Multi-stage + distroless/scratch |
| DB | Connection pooling, migrations |
| CI/CD | fmt, clippy, test, audit, build |
Congratulations on completing the series Rust: From Basics to Advanced! 🎉