- Khi tình trạng rò rỉ bộ nhớ và crash liên tục xảy ra trong Zig, ngôn ngữ không có an toàn bộ nhớ, Bun đã chuyển 535.496 dòng mã sang Rust bằng 64 agent AI, rút ngắn công việc vốn mất 1–2 năm xuống còn 11 ngày
- Điểm khởi đầu của thành công là
PORTING.mddài 600 dòng; quy trình diễn ra theo thứ tự: chuyển đổi song song theo từng tệp, hai lượt rà soát đối kháng, sửa lỗi biên dịch, kiểm thử cục bộ và vượt qua CI - Để tạo 6.500 commit, theo giá API đã tốn 165.000 USD, cùng 5,9 tỷ token đầu vào không cache, 690 triệu token đầu ra và 72 tỷ token đọc từ cache đầu vào
- Nếu làm thủ công, ước tính 3 kỹ sư hiểu rõ codebase sẽ phải dừng cải tiến sản phẩm, sửa lỗi/ bảo mật và phát triển tính năng mới trong khoảng 1 năm, nên việc tái viết gần như khó khả thi
- Để lặp lại cách làm này, cần kỹ sư hiểu sâu codebase, bộ kiểm thử mạnh đủ để tin cậy kết quả, và sẵn sàng chấp nhận chi phí token dù chưa chắc thành công
Vì sao Bun chọn tái viết bằng Rust
- Bun là một dự án production phức tạp, cung cấp nhiều chức năng vượt ra ngoài một JavaScript runtime
- Chuyển đổi JavaScript, TypeScript, CSS; bundling; minification
- Test runner và trình quản lý gói tương thích npm
- Phân giải module, WebSocket client, triển khai Node.js và nhiều module
- Lượt tải hằng tháng đạt 22 triệu, Claude Code và OpenCode phụ thuộc vào Bun, còn Vercel, Railway và DigitalOcean hỗ trợ trực tiếp
- Zig không phải ngôn ngữ an toàn bộ nhớ, nên ngay cả trong các bản Bun mới nhất vẫn tiếp tục có rò rỉ bộ nhớ, crash do vấn đề bộ nhớ, ghi ra ngoài phạm vi heap, v.v.
- Nhóm Bun đã vá Zig compiler và đưa vào kiểm thử rò rỉ bộ nhớ end-to-end, nhưng vẫn không loại bỏ được vấn đề
- Trong quá trình xử lý đồng thời vòng đời của giá trị garbage-collected và giá trị quản lý thủ công, các rò rỉ nhỏ và crash không thường xuyên phát sinh
- Với mọi cấp phát bộ nhớ, họ phải xem xét vị trí giải phóng, khả năng giải phóng trùng lặp, xử lý exception JavaScript, khả năng con trỏ hiển thị với conservative stack scanner, v.v.
- Trong Rust an toàn, use-after-free và double-free trở thành lỗi biên dịch, còn việc quên giải phóng trên nhánh lỗi có thể xử lý bằng cơ chế dọn dẹp tự động dựa trên
Drop - Nhóm cũng cân nhắc tự đưa smart pointer kiểu Rust vào mã Bun, nhưng cách này kém dễ dùng hơn Rust và không cung cấp cùng mức bảo đảm
Vì sao các dự án tái viết trước đây thường mất nhiều thời gian
- Trong khi tái viết, tính năng vẫn tiếp tục được thêm vào codebase gốc, nên thời điểm hoàn tất có xu hướng bị lùi đi lặp lại
- Công việc dự kiến 9 tháng có thể sau 9 tháng vẫn cần thêm khoảng 6 tháng nữa
- Sau 15 tháng vẫn có thể còn nhiều tháng làm việc để bắt kịp các tính năng mới
- Ngay cả khi may mắn, phải đóng băng tính năng trong 2 tháng rồi mới kết thúc sau khoảng 18 tháng; ước tính ban đầu 9 tháng có thể kéo dài thành hơn 2 năm
- Mã Zig của Bun, không tính chú thích, có 535.496 dòng, nên một nhóm kỹ sư nhỏ được dự đoán cần khoảng 1 năm để chuyển sang ngôn ngữ khác
- Vì việc dành 1 năm mà không có cải tiến thấy được với người dùng là không thực tế, họ quyết định thử xem có thể xác minh khả năng port sang Rust trong vòng một tuần bằng Fable hay không
Thiết kế và xác minh trước khi port
- Ở bước đầu, nhóm đã thảo luận với Claude trong khoảng 3 giờ về cách ánh xạ các pattern Zig sang Rust gần tương đương, rồi tổng hợp thành
PORTING.mddài 600 dòng - Hướng dẫn port chứa các ràng buộc cụ thể nhằm bảo toàn cấu trúc thực thi hiện có của Bun
- Không dùng
tokio,rayon,hyper,async-trait,futures - Cấm các module truy cập I/O như
std::fs,std::net,std::process - Vì Bun tự sở hữu event loop và system call, dùng callback và state machine như Zig hiện tại thay vì
async fn - Khi xảy ra xung đột với borrow checker, lưu các giá trị scalar cần thiết vào biến cục bộ, kết thúc borrow rồi borrow lại
- Cấm dùng raw pointer để né borrow checker, và để lại ghi chú port ở những chỗ đã thay đổi cấu trúc
- Không dùng
- Trong tổng số 1.448 tệp, trước tiên họ tái viết 3 tệp, rồi Claude rà soát đối kháng hai lần trong các phiên tách biệt với công việc chỉnh sửa
Làm việc song song với 64 agent AI
- Công việc được chia nhỏ để các tệp có thể xử lý độc lập với nhau, và 64 agent AI được chạy song song
- Ban đầu, nhiều agent cùng chạm vào trạng thái repository nên xảy ra xung đột
- Một agent chạy
git stash, sau đó agent khác chạygit stash popvàgit reset HEAD --hard - Nếu gán worktree riêng cho từng agent thì dung lượng đĩa bị thiếu do kích thước repository Bun, và cuối cùng vẫn có ràng buộc là các thay đổi phải được biên dịch cùng nhau
- Một agent chạy
- Họ sửa workflow bằng cách cấm các lệnh Git như
git stash,git reset, ngoại trừ lệnh commit ngay tệp cụ thể; đồng thời không cho dùngcargovà các lệnh chạy lâu - Cuối cùng, công việc được chia vào 4 worktree, mỗi worktree cấu hình 16 Claude commit và push tệp
- Trong hai ngày, các agent đã chuyển 535.496 dòng mã Zig; mỗi commit trải qua hai lượt rà soát đối kháng trước khi được áp dụng
Sửa lỗi biên dịch và kiểm thử
- Chuyển đổi ban đầu đã xong nhưng mã chưa biên dịch được, nên Claude sửa lỗi theo từng crate, đơn vị biên dịch cấp cao nhất của Rust
- Tiêu đề giai đoạn ghi khoảng 1.600 lỗi biên dịch, nhưng trong phần trích dẫn lại nói rằng trong quá trình giải quyết phụ thuộc vòng, khoảng 16.000 lỗi đã lộ ra
- Quá trình sửa lỗi cũng được song song hóa
- Chạy
cargo checkở từng crate - Gom output theo từng tệp và lưu tệp lỗi
- Sửa toàn bộ lỗi biên dịch của crate đó
- Hai người rà soát đối kháng kiểm tra các thay đổi
- Một agent phụ trách sửa phản hồi kết quả rà soát
- Chạy
- Các agent sửa lỗi biên dịch từ nửa đêm đến 11:30 sáng mà không có can thiệp của con người
- Sau đó, họ dành thêm khoảng hai ngày để bộ kiểm thử lớn có thể chạy cục bộ mà không còn lỗi biên dịch, rồi thêm vài ngày nữa để sửa các test thất bại và vượt qua CI
- Sau khi tất cả test đều qua và hành vi được xác nhận, thay đổi được merge; tổng thời gian từ lập kế hoạch đến hoàn tất là 11 ngày
- Port khoảng 550.000 dòng mã
- 6.500 commit
- Sử dụng 64 agent
Chi phí và kết quả so với làm thủ công
- Theo giá Fable API, tổng chi phí tái viết là 165.000 USD
- 5,9 tỷ token đầu vào không cache
- 690 triệu token đầu ra
- 72 tỷ token đọc từ cache đầu vào
- Vì Anthropic bán token API có cộng biên lợi nhuận, chi phí nội bộ thực tế thấp hơn con số này
- Chi phí API tương đương lương cơ bản hằng năm của một kỹ sư phần mềm doanh nghiệp bậc trung ở Mỹ, nhưng đánh giá cho rằng một kỹ sư ở cùng mức lương không thể tạo ra kết quả tương tự trong 11 ngày
- Điều này cũng phù hợp với nhận định của Mitchell Hashimoto rằng Fable đặc biệt xuất sắc ở các tác vụ khó và tập trung có hàm thưởng rõ ràng
- Nếu làm thủ công, ước tính cần 3 kỹ sư hiểu hoàn toàn codebase trong khoảng 1 năm
- Trong thời gian đó, sẽ khó cải thiện khả năng tương thích Node.js, sửa lỗi và vấn đề bảo mật, hay triển khai tính năng mới
- Phương án thực tế hơn là không tái viết và tiếp tục sửa các lỗi bộ nhớ hiện có
Điều kiện để áp dụng cho dự án khác
- Nếu AI có thể rút ngắn việc tái viết hoặc migration vốn mất 1 năm xuống mức khoảng một tuần, những dự án trước đây khó cân nhắc cũng trở nên có thể thực hiện
- Để tái sử dụng workflow của Bun, cần ba điều kiện
- Kỹ sư hiểu rất rõ codebase và có quyết tâm thực hiện
- Bộ kiểm thử đủ mạnh để có thể tin việc test pass là căn cứ cho hành vi thực tế
- Sẵn sàng đầu tư chi phí token đáng kể ngay cả khi chưa biết trước có thành công hay không
- Các công việc lặp lại như code migration là dạng LLM xử lý tương đối tốt, nên nếu có test tốt và kỹ sư biết tổ chức vấn đề, khả năng thành công sẽ cao
- Không phải dự án nào cũng cần 165.000 USD
- Dự án đơn giản hơn có thể có chi phí thấp hơn
- Có thể dùng model đắt nhất cho lập kế hoạch cấp cao, còn coding và review giao cho model rẻ hơn
- Migration dựa trên AI đang ngày càng nhanh hơn, nhưng chỉ những dự án được engineering tốt như Bun mới có thể đạt tốc độ như vậy
Chưa có bình luận nào.