Biên dịch JIT trong 5μs: Kỷ nguyên mới cho cơ sở dữ liệu nhờ AI

23 tháng 8, 2026·5 phút đọc

Bài viết khám phá cách xây dựng trình biên dịch JIT cực nhanh (5 micro giây) bằng kỹ thuật copy-and-patch và sự hỗ trợ của AI, giúp biên dịch mọi truy vấn SQL. Tác giả giới thiệu chi tiết mã máy ARM64 thông qua ví dụ về engine regex, đồng thời nhấn mạnh AI đã hạ thấp rào cản kỹ thuật cho các nhà phát triển cơ sở dữ liệu mới như pgrust.

Biên dịch JIT trong 5μs: Kỷ nguyên mới cho cơ sở dữ liệu nhờ AI

Biên dịch JIT trong 5μs: Kỷ nguyên mới cho cơ sở dữ liệu nhờ AI

Trình biên dịch Just-In-Time (JIT) từng được xem là "kỹ thuật đen" chỉ dành cho những lập trình viên assembly lành nghề. Tuy nhiên, với sự hỗ trợ của AI, việc viết một trình biên dịch JIT có tốc độ biên dịch cực nhanh (chỉ 5 micro giây) đã trở nên dễ dàng hơn bao giờ hết. Bài viết này sẽ hướng dẫn bạn xây dựng một trình biên dịch JIT đơn giản cho engine regex, đồng thời giải thích vì sao công nghệ này có thể tạo ra lợi thế cạnh tranh lớn cho các hệ quản trị cơ sở dữ liệu (DBMS) mới.

Vì sao cần biên dịch JIT?

Biên dịch JIT là kỹ thuật tạo mã máy tại thời điểm chạy, thay vì trước khi chạy. Khi được áp dụng đúng cách, nó có thể mang lại hiệu suất vượt trội, thường từ 2 đến 5 lần, thậm chí cao hơn. Điểm mạnh của JIT nằm ở việc tận dụng thông tin chỉ có được trong lúc runtime, ví dụ như schema của dữ liệu hay cấu trúc của câu lệnh truy vấn.

Trong lịch sử, không có cơ sở dữ liệu (DB) thương mại nào thực sự tự xây dựng trình biên dịch JIT cho riêng mình. Họ thường dùng LLVM hoặc sinh mã C/C++ — cả hai cách đều có thời gian biên dịch lớn, hạn chế khả năng ứng dụng. Đây chính là cơ hội cho các DB mới.

Xây dựng trình biên dịch JIT cho Regular Expression

Để minh họa, tác giả bài viết đã phát triển một engine regex "đồ chơi" hỗ trợ hai tính năng: chuỗi ký tự và phép lặp (dấu *). Chúng ta sẽ so sánh hiệu suất của ba cách triển khai: interpreter, mã viết tay, và mã JIT.

Kiến trúc của engine regex được đại diện bằng ba loại nút trong AST (cây cú pháp):

  • Literal: khớp một chuỗi cố định.
  • Concatenation: khớp nối tiếp hai node.
  • Repetition: lặp lại một node nhiều lần.

Phiên bản interpreter là code thuần Rust, dễ hiểu nhưng chậm. Điểm mấu chốt ở đây là cách tạo ra mã máy nhanh chóng.

Kỹ thuật Copy-and-Patch

Thay vì viết một trình tối ưu mã phức tạp, chúng ta dùng kỹ thuật copy-and-patch. Ý tưởng cốt lõi: chuẩn bị sẵn các "khuôn" mã máy (stencil) cho từng loại thao tác. Mỗi stencil có các vị trí "lỗ hổng" (hole) để chèn dữ liệu động như ký tự so sánh, địa chỉ nhảy (branch), hay giá trị tức thời (immediate).

Với regex b(an)*, trình biên dịch sẽ tạo ra các khối lệnh ARM64:

; PROLOGUE
mov x2, x1              ; Lưu địa chỉ đỉnh stack

; So khớp ký tự 'b'
ldrb w9, [x0]
cmp w9, #0x62           ; 'b'?
b.ne FAIL_BLOCK
add x0, x0, #1          ; Tiến tới ký tự tiếp theo

; SPLIT (bắt đầu vòng lặp lặp)
; Lưu địa chỉ thoát và vị trí hiện tại vào stack
; ... (các lệnh movz/movk để tạo địa chỉ tuyệt đối)
stp x9, x0, [x1], #16

; So khớp 'a'
ldrb w9, [x0]
cmp w9, #0x61
b.ne FAIL_BLOCK
add x0, x0, #1

; So khớp 'n'
ldrb w9, [x0]
cmp w9, #0x6e
b.ne FAIL_BLOCK
add x0, x0, #1

; Nhảy lên đầu vòng lặp
b SPLIT_BLOCK

; MATCH (thoát vòng lặp)
ldrb w9, [x0]
cbnz w9, FAIL_BLOCK      ; Nếu chưa hết chuỗi -> thất bại
mov x0, #1
ret

; FAIL_BLOCK (xử lý backtracking)
cmp x1, x2               ; Stack có frame nào không?
b.eq GIVE_UP
ldp x9, x0, [x1, #-16]!  ; Pop địa chỉ và vị trí
br x9                    ; Nhảy đến nơi cần quay lui

GIVE_UP:
mov x0, #0
ret

Điều thú vị là các stencil này được định nghĩa như các mảng u32 (mỗi phần tử là một lệnh ARM64), và trình biên dịch chỉ việc "lắp ráp" chúng lại với nhau.

Vai trò của AI

Tác giả chia sẻ rằng việc tự tay viết assembly là rất khó. Nhưng nhờ có AI, ông có thể mô tả ý tưởng tổng quát và để AI xử lý các chi tiết phức tạp như chọn lệnh, tính toán độ dịch chuyển địa chỉ.

"Đây là lĩnh vực mà tôi thấy AI hữu ích nhất. Tôi chưa bao giờ viết assembly thực thụ, nhưng với sự trợ giúp của AI, tôi có thể xây dựng một trình biên dịch JIT hoàn chỉnh."

Kết quả hiệu suất ấn tượng

Bảng so sánh hiệu suất giữa các phiên bản:

Độ dài inputInterpreterJITHandwrittenTốc độ JITTốc độ Handwritten
945 ns3.8 ns3.8 ns11.7x11.9x
33103 ns7.9 ns10.5 ns13.0x9.8x
129597 ns30 ns32 ns19.7x18.6x
5131,955 ns126 ns120 ns15.5x16.2x
2,0498,301 ns470 ns393 ns17.7x21.1x

Kết quả cho thấy JIT và mã viết tay có hiệu suất tương đương nhau, nhưng đều vượt trội so với interpreter (từ 12x đến 20x). Trong một số trường hợp, JIT còn nhanh hơn cả mã viết tay.

Kết luận và tương lai

Việc biên dịch JIT trong 5 micro giây mở ra khả năng biên dịch mọi câu lệnh SQL — không chỉ một tập con — giúp DB đạt hiệu suất tối đa. Điều này cho thấy AI không chỉ giúp viết code dễ hơn, mà còn giúp chúng ta tham vọng hơn trong việc xây dựng phần mềm phức tạp.

Tác giả kết luận:

"LLM đã hạ thấp rào cản gia nhập và giúp việc viết trình biên dịch JIT trở nên dễ dàng hơn nhiều. Đây chính là triết lý đằng sau dự án pgrust — một cơ sở dữ liệu mới, nhanh hơn nhờ ứng dụng AI vào chính quá trình phát triển."

Nếu bạn quan tâm đến việc xây dựng cơ sở dữ liệu hiệu năng cao, hoặc muốn tìm hiểu sâu về lập trình hệ thống, đây chắc chắn là một hướng đi đáng để khám phá và học hỏi.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗