- 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
- Demo liên quan được cung cấp dưới dạng bản ghi asciinema
- 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
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ườiNhì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
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áccomptimechậ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àocomptimeđể 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
comptimetại thời điểm biên dịch để xác định ánh xạ kiểu hàmCó 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
comptimeCụ 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.
Đâ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
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
real 0m18.444s,user 0m17.408s,sys 0m1.688sNgay 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 512KBTô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ó
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
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
Chương trình hello world tạo bằng
zig initkhi biên dịch ra 9,3MB. So với 7,6KB của-Doptimize=ReleaseSmallthì lớn hơn hơn 1000 lần, thật khổng lồ-OReleaseSmall -fno-striptạo ra file thực thi 580KB, còn-ODebug -fstriptạo ra file thực thi 1,4MBBackend 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
comptimehay chưa. Đó là chủ đề mới được bàn gần đâyCó 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
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ữ
@code_llvmđể hiển thị IRChẳ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
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ì?
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
switchXử 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ãcomptimecùng reflection kiểu như@typeInfoBằ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
GeneralPurposeAllocatorcũ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
gdbhaylldbcó 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 DWARFThê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
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...