Chuyển đến nội dung chính

Lesson 22: Production Deployment & Performance Tuning

Release profile optimization, LTO, codegen-units. Memory allocators (jemalloc, mimalloc). Connection pooling, request batching. Scaling strategies, microservices with Rust.

💻 Programming — Lesson 22 Lesson 22: Production Deployment & Performance Tuning

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;
AllocatorUse casesPros
System (default)GeneralNo extra dependencies
jemallocHigh-concurrency serversReduce fragmentation and multi-thread
mimallocGeneral, latency-sensitiveFast, compact, cross-platform

3. Performance Patterns

// 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

CategoryItem
BuildLTO enabled, single codegen-unit, stripped
Allocatorjemalloc or mimalloc
Loggingtracing + JSON format + RUST_LOG
MetricsPrometheus + Grafana
Health/health endpoint, readiness/liveness
Shut downGraceful shutdown (SIGTERM)
Securitycargo audit, cargo deny
DockerMulti-stage + distroless/scratch
DBConnection pooling, migrations
CI/CDfmt, clippy, test, audit, build

Congratulations on completing the series Rust: From Basics to Advanced! 🎉