Skip to content
JCJohnny Chung
← All posts

Làn sóng 'Rewrite in Rust' 2026: Từ Agent AI đến việc biên dịch ngược Rust sang C, Được gì, mất gì?

Phân tích sâu về trào lưu viết lại hệ thống bằng Rust qua case study Prime Agent và công cụ Eurydice biên dịch Rust sang C readable, cùng góc nhìn trade-off thực chiến.

· 7 min read

Rust code on screen

Ảnh: Juhan Sonin from Boston, USA, CC BY 2.0 qua wikimedia (nguồn)

Có câu đùa trong giới dev nghe ít nhất một lần mỗi quý: “Rewrite it in Rust”. Ban đầu là meme, nhưng gần đây hai câu chuyện trên Hacker News khiến người ta ngồi lại suy nghĩ: Prime Intellect công bố viết lại toàn bộ Prime Agent, hệ thống điều phối agent AI, sang Rust, và gần như cùng lúc, LWN đưa tin về Eurydice, công cụ biên dịch Rust ngược về C “đọc được”. Hai câu chuyện tưởng không liên quan, nhưng thực ra cùng kể một plot: Rust không còn ngách cho dân hệ thống, đang thành hạ tầng mặc định cho mọi thứ cần vừa an toàn vừa nhanh, kể cả khi downstream vẫn chạy C.

Bối cảnh: Vì sao agent AI lại cần Rust?

Prime Agent là một hệ thống orchestration, nó nhận request, phân phối cho các model, quản lý context, retry, tool-calling, streaming. Về bản chất nó là một I/O-bound system với concurrency rất cao. Câu hỏi đầu tiên bất kỳ tech lead nào cũng phải hỏi: tại sao không ở lại Python/TypeScript, nơi ecosystem AI tooling phong phú nhất?

Câu trả lời, theo blog Prime Intellect, xoay quanh ba điểm then chốt:

  1. Latency tail không chấp nhận được. Khi chạy hàng nghìn agent concurrent, GC pause của Python (hoặc kể cả Node’s V8 GC) tạo ra jitter không kiểm soát được ở p99. Với agent system, p99 latency ảnh hưởng trực tiếp đến trải nghiệm vì một agent chờ lâu có thể làm nghẽn cả chuỗi tool-call.
  2. Memory footprint khi scale theo chiều ngang. Mỗi agent instance trong Python dễ dàng tốn 200-400MB RSS chỉ để load runtime + dependencies. Nhân với hàng nghìn concurrent session, bill cloud compute tăng theo cấp số nhân.
  3. Correctness ở biên async. Đây là điểm đáng chú ý nhất. Khi logic retry, cancellation, timeout đan xen nhau trong async Python, race condition rất dễ lẻn vào vì type system không bắt được. Rust’s ownership model + Send/Sync traits buộc bạn phải nghĩ về concurrency safety ngay tại compile time, không phải lúc 3h sáng khi production alert nổ.

Điều thú vị là Prime Intellect không rewrite toàn bộ stack. Họ giữ Python cho research/prototyping (training loop, eval harness) và chỉ đẩy phần “hot path”, agent runtime, scheduler, tool dispatcher, sang Rust. Đây chính xác là pattern khuyên mọi team áp dụng: polyglot theo lớp, không rewrite nguyên khối.

// Ví dụ tối giản minh họa tool dispatcher pattern
// mà nhiều agent runtime Rust đang dùng
use tokio::sync::mpsc;
use std::collections::HashMap;

#[derive(Debug)]
enum ToolCall {
    Search { query: String },
    Execute { code: String, timeout_ms: u64 },
}

async fn dispatch(
    mut rx: mpsc::Receiver<ToolCall>,
    registry: HashMap<&str, Box<dyn ToolHandler>>,
) {
    while let Some(call) = rx.recv().await {
        // ownership model đảm bảo không có data race
        // dù hàng nghìn task chạy song song
        tokio::spawn(async move {
            match call {
                ToolCall::Search { query } => {
                    // handler tra registry, timeout tự động
                    // nhờ tokio::time::timeout bọc ngoài
                }
                ToolCall::Execute { code, timeout_ms } => {
                    // sandbox execution với budget rõ ràng
                }
            }
        });
    }
}

Cái hay ở đây không phải tốc độ raw (Rust nhanh hơn Python là điều ai cũng biết), mà là compile-time guarantee. Khi bạn có hàng chục agent chạy song song, mỗi agent gọi tool, retry, cancel lẫn nhau, việc compiler buộc bạn khai báo rõ ai own cái gì, ai được mutate cái gì, loại bỏ hẳn một lớp bug mà trong Python bạn chỉ phát hiện qua integration test hoặc, tệ hơn, qua production incident.

Server racks and infrastructure

Ảnh: Unnerving duck, BY-SA qua openverse (nguồn)

Phía bên kia: Eurydice và bài toán ngược, đưa Rust về C

Nếu Prime Agent là ví dụ cho “đi lên” (dùng Rust để thay thế code kém an toàn hơn), thì Eurydice là câu chuyện “đi xuống”, biên dịch Rust về C để chạy trên môi trường mà Rust chưa (hoặc không thể) đặt chân tới.

Eurydice, công cụ được giới thiệu trên LWN, lấy một subset Rust (thực chất là lấy từ dự án F* verification toolchain, qua trung gian là ngôn ngữ trung gian Low*) và sinh ra C code đọc được, tức không phải obfuscated C mà con người có thể review, audit, và tích hợp vào codebase C hiện có. Use case chính: embedded systems, firmware, hoặc bất kỳ môi trường nào mà toolchain Rust chưa được certify (automotive ISO 26262, avionics DO-178C, hoặc đơn giản là một legacy build system chỉ hiểu Makefile + GCC từ 2005).

Tại sao điều này quan trọng với tôi? Vì nó giải quyết đúng cái paradox mà bất kỳ ai làm hệ thống safety-critical đều gặp: bạn muốn viết logic bằng Rust để có borrow checker, để loại bỏ buffer overflow, use-after-free ngay từ lúc code; nhưng bạn không thể ship Rust runtime vào một hệ thống mà regulator chỉ chấp nhận C đã được certify qua hàng chục năm.

Eurydice không đứng một mình, nó nằm trong hệ sinh thái với HACL* (thư viện crypto được Mozilla, Linux kernel dùng, viết bằng F*, biên dịch ra C qua KaRaMeL/Eurydice). Nói cách khác: formal verification ở tầng cao (F) → logic an toàn tầng giữa (Rust-like) → C code production-ready ở tầng thấp.* Đây là một pipeline này sẽ ngày càng phổ biến trong 3-5 năm tới, đặc biệt khi các CVE liên quan đến memory safety trong C/C++ (chiếm khoảng 70% CVE nghiêm trọng theo báo cáo của Microsoft và Google) tiếp tục là áp lực buộc ngành phải tìm lối thoát mà không phá vỡ toolchain cũ.

Trade-off thật, không tô vẽ

Sẽ thẳng thắn về những thứ mà cả hai câu chuyện trên đều không nói to lên:

1. Compile time và iteration speed giảm mạnh. Khi team rewrite phần core service sang Rust, build time từ cargo check tăng từ gần như instant (Python) lên 15-40 giây cho incremental build, và full build CI/CD tăng gấp 3-4 lần so với khi còn Go/Python. Với team làm research cần iterate nhanh, đây là cái giá không nhỏ. Prime Intellect giải quyết bằng cách giữ research loop ở Python và chỉ đưa runtime ổn định sang Rust, đúng chiến lược, nhưng không phải team nào cũng có đủ ranh giới rõ ràng để làm vậy.

2. Hiring và ramp-up cost. Borrow checker là con dao hai lưỡi: nó bắt bug tại compile time, nhưng cũng là lý do khiến một dev mid-level mất 2-3 tuần đầu chỉ để “thương lượng” với compiler thay vì ship feature. Nếu đội của bạn chủ yếu là Python/TS dev, budget cho ramp-up này phải được tính vào roadmap, không phải một “side quest”.

3. Ecosystem gap vẫn còn, dù đã thu hẹp nhiều. Muốn làm agent orchestration với LLM provider SDK, ở Python bạn có LangChain, OpenAI SDK, hàng trăm integration sẵn. Ở Rust, bạn thường phải tự viết wrapper hoặc dùng crate ít người maintain. Prime Agent chấp nhận trade-off này vì lợi ích latency/safety đủ lớn để bù lại effort tự build; nhưng với một startup 3 người cần ship MVP trong 2 tuần, đây có thể là quyết định tự sát.

4. Với Eurydice, verification không miễn phí. Viết code theo style mà Low*/F* có thể biên dịch được đòi hỏi bạn từ bỏ nhiều pattern Rust “tự nhiên”, generic phức tạp, trait object, closure linh hoạt, để giữ trong subset có thể formal-verify. Bạn đang đánh đổi ergonomics của Rust để lấy formal guarantee. Đây là lựa chọn hợp lý cho crypto primitive hay flight control, nhưng hoàn toàn overkill cho một CRUD backend.

Circuit board close up

Ảnh: Raimond Spekking, BY-SA qua openverse (nguồn)

Khi nào nên, và không nên, nhảy vào làn sóng này

Sau nhiều năm quan sát các cuộc rewrite, rút ra một checklist thực dụng:

Nên xem xét Rust khi:

  • Hot path của bạn bị giới hạn bởi GC pause hoặc memory overhead, và bạn đã đo đạc (profiling thật, không phải cảm tính) rằng đây là bottleneck chính.
  • Concurrency bug (race condition, data race) đã từng gây incident production ít nhất 2 lần trong 6 tháng qua.
  • Bạn cần ship cùng một logic core cho nhiều target (server, WASM client, embedded), đây là lúc “write once, compile everywhere” của Rust tỏa sáng thật sự, không chỉ marketing.
  • Compliance/safety certification yêu cầu memory-safety guarantee mà ngôn ngữ cũ không cung cấp được.

Không nên vội khi:

  • Bottleneck của bạn là network I/O hoặc database latency, Rust không giải quyết được vấn đề này nhanh hơn một service Go hay Node được viết tốt.
  • Team chưa có ít nhất 1-2 người thực sự thoải mái với ownership model, lifetime, và async runtime của Rust (tokio/async-std) để làm mentor cho phần còn lại.
  • Dự án đang ở giai đoạn product-market fit chưa rõ ràng, lúc này velocity để thử nghiệm quan trọng hơn performance tuyệt đối.

Kết luận: Rust đang trở thành “lingua franca” của tầng hạ tầng, không phải phép màu