1 điểm bởi GN⁺ 2025-06-09 | 1 bình luận | Chia sẻ qua WhatsApp
  • Zig đã thay đổi đường dẫn mặc định trước đây, trong đó LLVM hạ bitcode xuống file object trên target x86_64, sang backend x86 tự host, giúp giảm đáng kể tốc độ biên dịch và mức dùng bộ nhớ của các bản build debug
  • Backend x86 tự host vượt qua 1.987 behavior test, nhiều hơn 1.980 test của backend LLVM; trong tổng số 2.084 test, một số test bổ sung chỉ được chạy trong các bài test x86 self-hosted
  • Trong benchmark hello.zig, thời gian trung bình của đường dẫn LLVM là 918ms giảm xuống 275ms với backend tự host mặc định, wall time giảm 70,1%, và peak RSS cũng giảm từ 214MB xuống 137MB
  • Ngay cả với các dự án lớn như chính Zig compiler, thời gian build cũng giảm từ 75 giây xuống 20 giây, nhưng Windows chưa nằm trong diện chuyển mặc định vì cần thêm công việc cho COFF linker
  • Các việc còn lại gồm song song hóa hoàn toàn code generation, cải thiện linker, ổn định incremental compilation, cải thiện chất lượng mã x86 và mở rộng backend aarch64

Chuyển backend mặc định cho x86_64

  • Khi build cho target x86_64, Zig hiện mặc định dùng backend x86 tự host
  • Đường dẫn mặc định trước đây là cách LLVM hạ file bitcode xuống file object
  • Trên Windows, mặc định vẫn chưa được thay đổi
    • Vì cần thêm công việc cho COFF linker

Tình hình vượt qua behavior test

  • Backend x86 tự host vượt qua 1.987 behavior test
  • Backend LLVM vượt qua 1.980 behavior test
  • Tổng số behavior test là 2.084, nhưng các test bổ sung phần lớn trùng với các test backend x86 của chính LLVM
    • Những test bổ sung này chỉ chạy khi test x86 self-hosted
  • Xét theo số test vượt qua, backend x86 của Zig đang ở trạng thái tiến xa hơn backend LLVM trong phần triển khai ngôn ngữ Zig

Vì sao cạnh tranh với đường dẫn LLVM

  • Lý do lớn nhất khiến Zig cạnh tranh với LLVM ở phần code generation là vì có thể tạo ra chênh lệch lớn về tốc độ biên dịch
  • Bối cảnh liên quan được tóm tắt trong phần giải thích trên Ziggit

Benchmark hello.zig

  • Kết quả zig build-exe hello.zig -fllvm:
    • Wall time trung bình: 918ms
    • peak RSS: 214MB
    • CPU cycles: 4.53G
    • instructions: 8.50G
  • Kết quả đường dẫn mặc định zig build-exe hello.zig:
    • Wall time trung bình: 275ms
    • peak RSS: 137MB
    • CPU cycles: 1.57G
    • instructions: 3.21G
  • Backend tự host mặc định giảm nhiều chỉ số so với đường dẫn LLVM
    • wall time giảm 70,1%
    • peak RSS giảm 36,2%
    • CPU cycles giảm 65,2%
    • instructions giảm 62,2%
    • cache misses giảm 86,1%
    • branch misses giảm 78,3%

Hiệu quả trong các dự án lớn

  • Với các dự án lớn hơn như chính Zig compiler, thời gian build giảm từ 75 giây xuống 20 giây
  • Backend x86 tự host có thể giảm đáng kể thời gian biên dịch không chỉ với ví dụ nhỏ mà cả với codebase lớn

Công việc tiếp theo

  • Zig đã bắt đầu công việc song song hóa hoàn toàn code generation
  • Khi việc cải thiện linker và sửa lỗi tiến triển thêm, incremental compilation có thể trở nên ổn định và vững chắc cùng với backend này
  • Chất lượng mã x86 được tạo ra vẫn còn dư địa để cải thiện
  • Mục tiêu tiếp theo là aarch64, và công việc được kỳ vọng sẽ tăng tốc nhờ Legalize pass mới
  • Có thể tải bản build master branch mới nhất từ trang tải xuống Zig để tự thử nghiệm

1 bình luận

 
GN⁺ 2025-06-09
Các ý kiến trên Hacker News
  • Theo tôi biết, Zig đang có rất nhiều việc đang được thực hiện để mang lại trải nghiệm phát triển tốt hơn. Gần như ngày nào cũng có thứ gì đó được làm, và vừa rồi cũng có một PR như https://github.com/ziglang/zig/pull/24124 được đưa lên
    Tôi nhớ trước đây họ cũng từng lên kế hoạch cho hot code replacement, và với tốc độ phát triển hiện tại thì tôi cũng sẽ không ngạc nhiên nếu nó chạy được trên x86_64 trong vòng 1 năm
    Hiện tại nỗi đau lớn nhất của cá nhân tôi là tốc độ comptime. Trình biên dịch còn nhiều việc phải làm ở đây, và việc chạy một DSL brainF** vào thời điểm biên dịch thì khá chậm. Tôi đã tự thử, và đúng là một thí nghiệm buồn cười
    Nhìn chung tôi rất kỳ vọng vào các backend mới mà Zig đang đưa vào. Tôi muốn tự làm thử một backend URCL(https://github.com/ModPunchtree/URCL) cho Zig

    • Về cải thiện hiệu năng comptime, họ biết cần phải làm gì, và từ lâu trước đây cũng đã bắt đầu làm trên một nhánh. Tuy nhiên vì phải làm lại khá nhiều mã phân tích ngữ nghĩa, nên đây chắc chắn là việc có thể làm, nên làm và sẽ làm, nhưng hiện đang phải cạnh tranh với các ưu tiên khác
    • Hot code replacement sẽ cực kỳ lớn đối với phát triển game. Ý tưởng rằng Zig gần như sẽ hỗ trợ sẵn chỉ bằng một cờ trình biên dịch là rất ấn tượng. Tôi muốn thấy ai đó thử làm như vậy với clang
    • Tôi tự hỏi liệu việc comptime chậm có thật sự là vấn đề không. Tôi đang làm một thư viện JSON-RPC, và đang phụ thuộc nhiều vào comptime để dispatch các yêu cầu JSON tới các hàm tùy ý
      Vì kiểu tĩnh nghiêm ngặt nên không có cách nào dispatch động ở runtime tới một hàm có các tham số tùy ý, và cách duy nhất tôi tìm được là dùng comptime tại thời điểm biên dịch để xác định ánh xạ kiểu hàm
      Có vẻ kích thước mã sẽ tăng lên vì mỗi hàm tùy ý lại có thêm một bản sao mã đã được comptime
    • Tôi tò mò liệu có dễ tạo backend tùy chỉnh không. Tôi chưa xem, nhưng muốn thử nghiệm
      Cụ thể, có vẻ có thể tạo một backend nhận AIR rồi tạo báo cáo an toàn bộ nhớ. Kiểu như nhận diện việc dùng giá trị chưa xác định, con trỏ stack thoát ra ngoài, use-after-free, double free, alias xor mut, v.v.
    • Tôi đang sa vào hang thỏ vì URCL. Chưa xem sâu, nhưng dòng thời gian buồn cười nhất sẽ là việc biểu diễn trung gian được tạo cho Minecraft trở thành một đích biên dịch thực dụng cho nhiều ngôn ngữ
  • Đây đã là một thành tựu rất lớn rồi, nhưng như ghi trong nhật ký phát triển, phía trước vẫn còn nhiều thứ hơn nữa. Ý tưởng về một trình biên dịch chỉ sửa những phần cần thiết trong binary khi biên dịch vừa mới mẻ vừa hoàn toàn đột phá, và có vẻ giờ đã nằm trong tầm với của dự án Zig
    Rất đáng mong chờ

  • Tôi thấy phần “một dự án lớn như trình biên dịch Zig giảm từ 75 giây xuống 20 giây. Đây mới chỉ là khởi đầu” rất đáng kỳ vọng. Tôi tò mò người này có thể làm được gì với nó, và trông anh ấy thật sự rất thông minh
    Tôi không rõ quản lý gói hiện ở trạng thái nào. Tôi từng thử làm một ứng dụng QuickJS + SDL3, nhưng vì sự rối rắm phía C++ nên đã chuyển sang Rust, và ở đó thì mọi thứ chạy ổn. Hy vọng cũng có thể thử trong Zig

    • Quản lý gói của Zig thủ công hơn Rust. Cách làm là dùng CLI lấy URL gói, rồi import module trong script build
      Nó cũng có ưu điểm: có thể phụ thuộc vào các archive tùy ý, và nhiều gói Zig bọc thư viện C thực chất cũng gần giống các script build phụ thuộc vào bản phát hành tarball chưa chỉnh sửa. Tất nhiên với người mới thì sẽ khó hơn một chút
      SDL3 có wrapper Zig native: https://github.com/Gota7/zig-sdl3
      Cũng có bản repackaging thư viện/API C ở mức cơ bản hơn: https://github.com/castholm/SDL
      Với QuickJS thì C API là lựa chọn duy nhất: https://github.com/allyourcodebase/quickjs-ng
      Zig làm cho việc dùng trực tiếp các gói C kiểu này trở nên rất dễ, nhưng kiểu của Zig nghiêm ngặt hơn nhiều nên khi tương tác với API bạn sẽ phải cast khá nhiều
    • Trình biên dịch D dmd có thể biên dịch chính nó ở bản debug
      real 0m18.444s, user 0m17.408s, sys 0m1.688s
      Ngay cả trên một bộ xử lý rất cũ cũng được như vậy, nên vì nó chạy quá nhanh nên tôi chẳng cần nâng cấp
      Thông số kiểu như AMD Athlon(tm) 64 X2 Dual Core Processor 4400+, 2 lõi, 2.3GHz, cache 512KB
    • Tôi tò mò có hướng dẫn nào để làm việc đó không. Khi tôi thử biên dịch Zig thì mất nhiều bước và khá lâu, bao gồm cả toàn bộ quá trình bootstrap trong wasm
    • Việc Zig có thể biên dịch chính nó trong 75 giây thật đáng kinh ngạc. Ngay cả khi dùng LLVM cũng vậy
  • Tôi đã nói điều này thời D và Nature rồi: với mọi ngôn ngữ có backend riêng, chúng ta có nghĩa vụ ủng hộ các dự án không muốn phụ thuộc vào LLVM
    Có vẻ LLVM đã khiến R&D trình biên dịch bị đình trệ, quá nhiều ngôn ngữ chọn phụ thuộc vào LLVM, và quá nhiều người không còn coi thời gian lặp nhanh là có giá trị, hoặc không còn kỳ vọng vào điều gì tốt hơn
    Lặp nhanh bằng biên dịch tăng dần và vá binary, đồng thời debug tốt, nên trở thành kỳ vọng đối với các ngôn ngữ mới, chứ không nên bị xem là tính năng ngách hay việc quá khó

    • Ngược lại, LLVM cũng đã khiến các ngôn ngữ do cá nhân tạo ra có ngay hiệu năng cạnh tranh và hỗ trợ nền tảng rộng, nhờ đó bùng nổ về số lượng. Zig cũng là một trong số đó
      Toàn bộ ngành kết xuất thời gian thực trên thực tế được xây dựng trên LLVM hoặc các fork của LLVM; Microsoft cũng đã chuyển trình biên dịch shader sang LLVM và giờ mới bắt đầu upstream mã
      Phần lớn hạ tầng trình biên dịch của các máy chơi game console cũng dựa trên Clang. Xbox đến nay vẫn bám MSVC, nhưng gần như là ngoại lệ
      Nhìn chung, LLVM đã cực kỳ thành công, đặc biệt trong việc bootstrap những thứ mới
    • Đúng vậy. Một trong số ít điểm tôi đánh giá tích cực ở Go là việc nó đã được bootstrap và không phụ thuộc vào LLVM
  • Không muốn nghe như đang đòi hỏi hay không biết ơn. Zig là công việc được làm miễn phí mà. Chỉ là điều mình tò mò nhất là lịch trình 1.0 thực tế
    Zig gần như khớp chính xác với những gì mình mong muốn ở một ngôn ngữ cấp thấp, và mình đang chờ nó ổn định
    Tất nhiên mình thật sự biết ơn triết lý thiết kế tối giản của Zig

    • Các dự án nghiêm túc như TigerBeetle thường ghim phiên bản, có lẽ là dùng bản phát hành mới nhất. Mình xem nightly gần với mục đích thử nghiệm hơn
  • Chương trình hello world tạo bằng zig init khi biên dịch ra 9,3MB. So với 7,6KB của -Doptimize=ReleaseSmall thì lớn hơn hơn 1000 lần, thật khổng lồ

    • Quan sát đó đúng. Một quan sát khác là 82% trong số đó là thông tin debug
      -OReleaseSmall -fno-strip tạo ra file thực thi 580KB, còn -ODebug -fstrip tạo ra file thực thi 1,4MB
      Backend x86 của Zig mang lại trải nghiệm debug tốt hơn nhiều khi dùng cùng một fork lldb hiểu Zig: https://github.com/ziglang/zig/wiki/LLDB-for-Zig
      Mình không nhớ hiện có thể step qua logic comptime hay chưa. Đó là chủ đề mới được bàn gần đây
  • Có vẻ Julia nên cân nhắc chuyển sang Zig nếu muốn đạt được mức tăng hiệu năng đáng kể. Mình nhớ các tác giả Julia từng lo lắng mỗi khi LLVM phát hành, sợ bị giảm hiệu năng

    • Julia thực ra gắn rất chặt với LLVM. Một phần lớn hệ sinh thái phụ thuộc vào sự tồn tại của LLVM vì intrinsic, tự động vi phân (Enzyme), và biên dịch GPU. Chưa kể Base và Core
      Trình biên dịch khá có khả năng retarget, và đây cũng là một lĩnh vực đang được phát triển tích cực. Vì vậy trong tương lai, có lẽ có thể tưởng tượng Zig như một trình biên dịch thay thế cho một số mảnh của ngôn ngữ
    • LLVM chẳng phải được xem là một phần API công khai của Julia sao? Thực tế có các macro như @code_llvm để hiển thị IR
    • Nó có thể là một cách để giảm thời gian biên dịch, nhưng mình nghĩ phía Julia vẫn còn nhiều việc phải làm
      Chẳng hạn cache biên dịch chi tiết hơn, công cụ tốt hơn để ngăn invalidation, loại bỏ tối ưu hóa world splitting, tận dụng đa luồng trong trình biên dịch nhiều hơn, tự động tiền biên dịch các signature cụ thể, và sinh mã lười hơn để hot-swap code khi đã biên dịch
    • Mỗi khi có backend trình biên dịch mới là lại có những nhận định như vậy. Mình khá hoài nghi, nhưng nếu ai đó nhận làm thành dự án thì cũng thú vị để xem chuyện gì sẽ xảy ra
  • Với góc nhìn của một người hoàn toàn mới, mình tò mò Zig tốt hơn các ngôn ngữ khác ở điểm nào. Mình hiểu nó là một C hiện đại hơn, vậy phần hiện đại đó là gì?

    • Chỉ liệt kê vài thứ nghĩ ra ngay: có hệ thống build tích hợp, không phải dùng nhiều công cụ và ngôn ngữ riêng rẽ khó hiểu
      Khác với mảng của C, Zig có slice biết độ dài nên tốt hơn về mặt tránh tràn bộ đệm, các optional type rõ ràng bắt buộc phải được kiểm tra, và không cho phép con trỏ null. Ngay cả khi được phép trong lúc tích hợp với code C, kiểu dữ liệu cũng thể hiện rõ điều đó
      Cũng có enum, tagged union, và kiểm tra tính bao phủ bắt buộc trong biểu thức switch
      Xử lý lỗi là tường minh: hàm trả về lỗi (giá trị enum) mà caller phải xử lý theo cách nào đó. Trong C, kể cả khi hàm trả về số nguyên biểu thị lỗi, bạn vẫn có thể hoàn toàn phớt lờ
      Tuy nhiên, ngôn ngữ chưa tích hợp sẵn một cách chuẩn để trả về dữ liệu kèm lỗi. Mẫu truyền struct lỗi qua tham số có cảm giác như phần thêm vào, nên mình nghĩ đáng ra nên có cú pháp đặc biệt cho việc này
      Có các khối defer, errdefer để dọn dẹp sau khi hàm trả về hoặc phát sinh lỗi, và thay vì macro có thể dùng sinh mã comptime cùng reflection kiểu như @typeInfo
      Bằng cách truyền allocator cho thư viện, caller thường quyết định bộ nhớ sẽ được cấp phát ở đâu và như thế nào; chỉ cần dùng GeneralPurposeAllocator cũng đã dễ phát hiện rò rỉ bộ nhớ
      Sau khi bắt đầu lập trình, mình luôn dùng các ngôn ngữ cấp cao và ghét những điểm khó hiểu, phản trực giác của C cùng hệ sinh thái quanh nó; nhờ Zig mà lần đầu tiên mình thấy lập trình hệ thống trở nên thú vị
  • Đây chỉ là thay backend thôi à? Mình tò mò liệu toàn bộ các pass phân tích và kiểu vẫn còn đó, hay phần kiểm chứng cũng được giảm bớt
    Vòng biên dịch nhanh giúp tăng năng suất, nhưng mình nghĩ chỉ đúng khi nó bao gồm cả test nhanh
    Nếu vậy, chẳng phải chạy Zig bằng interpreter cho debug sẽ dễ hơn sao? Như thế có vẻ cũng giải quyết được vấn đề phải lặp lại công việc cho từng target

    • Trọng tâm của chế độ debug là khả năng debug, và việc gắn Zig chạy bằng interpreter vào các debugger tiêu chuẩn như gdb hay lldb có lẽ không hề đơn giản. Vì các công cụ đó kỳ vọng file thực thi có thông tin debug DWARF
      Thêm nữa, đặc biệt trong các lĩnh vực như phát triển game, hiệu năng chế độ debug thực sự cũng rất quan trọng
    • Thứ được thay chỉ là backend. Test cũng sẽ nhanh hơn
      Không có nhu cầu thực tế để thêm interpreter. Việc có backend tùy chỉnh nghĩa là hiện tại nó được dùng cho debug, nhưng trong tương lai xa hơn nhiều, nó cũng có thể cạnh tranh với LLVM về tốc độ
      Thêm interpreter thì dù sao vẫn phải viết backend tùy chỉnh, nên ít hữu ích
      Vấn đề là LLVM chậm ở cả debug lẫn release
  • Đây chẳng phải là một trong các điều kiện tiên quyết để đưa async/await trở lại Zig sao?
    https://github.com/ziglang/zig/wiki/FAQ#what-is-the-status-o...

    • Phần đó đã được sắp xếp xong, và có lẽ trong 2–3 tháng tới chúng tôi có thể chia sẻ một cập nhật thú vị. I/O đang được làm lại từ nền tảng, và phần lớn là công việc ở thư viện chuẩn
    • Đọc link thì có vẻ async sẽ không quay lại, hoặc ít nhất là không trước năm 2028