So sánh hiệu năng giữa C và Rust cho các extension phân tích số trong SQLite
Simon Willison đã so sánh các bản triển khai bằng C và Rust của extension parse_number() trong SQLite, phát hiện ra rằng phiên bản C được tối ưu hóa đạt tốc độ 16-19 ns mỗi dòng.
Bài được dịch tự động từ bản gốc tiếng Anh.
Nhà phát triển Simon Willison đã công bố một bài kiểm tra hiệu năng kỹ thuật vào ngày 8 tháng 11 năm 2026, so sánh hiệu suất và độ phức tạp khi xây dựng extension tùy chỉnh cho SQLite bằng ngôn ngữ C so với Rust. Nghiên cứu tập trung vào hàm parse_number() được thiết kế để làm sạch dữ liệu chuỗi lộn xộn thành các giá trị số, cho thấy rằng một bản triển khai C được tối ưu hóa cao có thể vượt qua các bản tương đương bằng Rust về tốc độ thô, đồng thời duy trì kích thước file nhị phân nhỏ hơn đáng kể.
Diễn biến sự việc
Willison bắt đầu thử nghiệm này khi đang dắt chó đi dạo, tò mò về những khác biệt thực tế giữa việc viết extension SQLite bằng C hoặc Rust. Ông sử dụng một trợ lý AI để tạo ra các nguyên mẫu ban đầu cho cả hai ngôn ngữ, nhằm mục đích tạo ra một hàm loại bỏ ký hiệu tiền tệ, dấu phẩy và dấu phần trăm khỏi các chuỗi như -$1,234.56 hoặc '12.5%'. Mục tiêu là trả về một giá trị số hợp lệ để tính tổng và sắp xếp, hoặc NULL nếu đầu vào không thể phân tích được. So sánh ban đầu cho thấy các extension Rust có dung lượng file lớn hơn nhưng lại nhanh hơn bất ngờ so với bản triển khai C đơn giản (naive), vốn dựa vào hàm strtod của thư viện chuẩn.
Để giải quyết khoảng cách hiệu năng, Willison đã yêu cầu AI viết một hàm phân tích C tùy chỉnh với đường dẫn nhanh gọn nhẹ (compact fast path), bỏ qua các lời gọi thư viện chuẩn chậm hơn dành cho xử lý số thập phân. Phiên bản C được tối ưu hóa này đã thu hẹp khoảng cách và cuối cùng vượt qua các bản triển khai Rust về tốc độ. Kết quả cuối cùng cho thấy mã C mới xử lý dữ liệu hỗn hợp trong 19 nano giây mỗi dòng, so với 41-46 nano giây đối với các phiên bản Rust. Thí nghiệm kết thúc với việc AI tạo ra một báo cáo nghiên cứu đầy đủ định dạng cho kho lưu trữ công khai của Willison, ghi lại mã nguồn, các bài kiểm tra và chỉ số hiệu năng.
Chi tiết chính
- Extension C được tối ưu hóa đạt thời gian xử lý 16–19 nano giây mỗi dòng, nhanh gấp đôi so với các phiên bản Rust.
- Dung lượng file khác nhau đáng kể: extension C chỉ nặng 14 KB, trong khi các phiên bản Rust dao động từ 298 KB đến 321 KB.
- Mã C ban đầu chậm hơn khi xử lý số thập phân do phụ thuộc vào
strtod, nhưng một đường dẫn nhanh tùy chỉnh đã giải quyết nút thắt cổ chai này. - Cả bốn bản triển khai đều vượt qua 8 triệu lần kiểm tra fuzzing, đảm bảo hành vi nhất quán và độ chính xác trên các trường hợp biên.
- Bản triển khai Rust sử dụng
rusqlitemất 46 ns cho dữ liệu hỗn hợp, trong khisqlite-loadable-rsmất 41 ns. - Bản triển khai C cuối cùng xử lý số nguyên trong 16 ns và số thập phân trong 18 ns, vượt trội hơn so với mức 32-36 ns và 47-55 ns tương ứng của Rust.
Bối cảnh
SQLite là một engine cơ sở dữ liệu nhúng phổ biến, cho phép các nhà phát triển mở rộng chức năng thông qua các hàm tùy chỉnh được viết bằng các ngôn ngữ biên dịch như C hoặc Rust. Các extension này chạy trực tiếp trong tiến trình cơ sở dữ liệu, khiến chúng lý tưởng cho các tác vụ chuyển đổi dữ liệu hiệu năng cao như làm sạch các bản ghi nhập khẩu. Khi chọn ngôn ngữ cho các extension này, các nhà phát triển thường cân nhắc giữa sự dễ dàng trong phát triển và an toàn bộ nhớ so với tốc độ thực thi thô và kích thước file nhị phân. C cung cấp chi phí thấp nhất và các file nhị phân siêu nhỏ nhưng đòi hỏi quản lý bộ nhớ thủ công, trong khi Rust cung cấp các đảm bảo an toàn mạnh mẽ nhưng phải đánh đổi bằng kích thước file nhị phân lớn hơn và đặc điểm runtime có thể khác biệt.
Hàm parse_number() giải quyết một vấn đề kỹ thuật dữ liệu phổ biến: chuyển đổi các chuỗi được định dạng theo cách con người đọc hiểu sang các số máy có thể đọc được. Các hàm SQL tiêu chuẩn như replace() có thể loại bỏ ký tự nhưng thường chậm khi áp dụng từng dòng trên các tập dữ liệu lớn. Các extension tùy chỉnh bỏ qua một số chi phí này bằng cách hoạt động gần với phần cứng hơn. Tuy nhiên, việc viết các parser hiệu quả trong C đòi hỏi sự tối ưu hóa cẩn thận để tránh những bẫy của các hàm chuyển đổi đa dụng, vốn có thể không xử lý hiệu quả các đặc điểm định dạng cụ thể.
Tại sao điều này quan trọng
Đối với các đội ngũ quản lý cơ sở dữ liệu tự host hoặc xây dựng các ứng dụng chuyên sâu về dữ liệu, bài kiểm tra hiệu năng này làm nổi bật những đánh đổi hữu hình giữa sự tiện lợi trong phát triển và hiệu quả vận hành. Mặc dù Rust mang lại trải nghiệm phát triển an toàn hơn và công cụ hỗ trợ mạnh mẽ, nhưng hình phạt về hiệu năng trong micro-benchmark cụ thể này là đáng kể. Đối với các pipeline nhập dữ liệu khối lượng lớn, nơi mỗi nano giây đều quý giá, khả năng vắt kiệt hiệu năng tối đa từ C có thể giảm chi phí hạ tầng và cải thiện thông lượng. Tuy nhiên, điều này đi kèm với trách nhiệm quản lý an toàn bộ nhớ và các lỗi tiềm ẩn một cách thủ công.
Nghiên cứu cũng nhấn mạnh vai trò ngày càng tăng của các trợ lý AI trong lập trình hệ thống ở tầng thấp. Bằng cách tận dụng AI để tạo và tối ưu hóa mã C phức tạp, các nhà phát triển có thể tiếp cận các mức hiệu năng mà nếu không sẽ đòi hỏi chuyên môn sâu về lập trình hệ thống. Điều này dân chủ hóa quyền truy cập vào các extension cơ sở dữ liệu hiệu năng cao, cho phép các đội ngũ nhỏ hơn triển khai các tối ưu hóa tùy chỉnh mà không cần thuê các kỹ sư C chuyên nghiệp. Nó gợi ý rằng rào cản gia nhập để viết các plugin cơ sở dữ liệu hiệu quả đang giảm xuống, miễn là bạn biết cách hướng dẫn công cụ một cách hiệu quả.
Bạn có thể làm gì
- Đánh giá các pipeline làm sạch dữ liệu hiện tại của bạn để xác định các nút thắt cổ chai, nơi các extension SQLite tùy chỉnh có thể thay thế các hàm SQL chậm hơn.
- Cân nhắc sử dụng C cho các extension quan trọng về hiệu năng nếu đội ngũ của bạn có chuyên môn để quản lý an toàn bộ nhớ và kiểm thử một cách nghiêm ngặt.
- Sử dụng Rust cho các extension nơi tốc độ phát triển, an toàn bộ nhớ và khả năng bảo trì là ưu tiên cao hơn so với hiệu năng thô ở mức nano giây.
- Triển khai kiểm thử fuzzing toàn diện cho bất kỳ logic phân tích tùy chỉnh nào để đảm bảo nó xử lý tốt các đầu vào bất ngờ hoặc sai định dạng.
- Kiểm tra hiệu năng (benchmark) cho các trường hợp sử dụng cụ thể của bạn thay vì dựa vào các giả định chung, vì hiệu năng có thể thay đổi dựa trên phân phối dữ liệu và phần cứng.
- Tận dụng các công cụ AI để tạo nguyên mẫu và tối ưu hóa mã ở tầng thấp, nhưng luôn xác minh đầu ra được tạo ra bằng kiểm thử nghiêm ngặt và rà soát mã nguồn.



