- Biến mã Ruby thành binary native độc lập có thể thực thi, và nhắm tới tốc độ chạy nhanh hơn trung bình nhân khoảng 11,6 lần so với CRuby
miniruby mới nhất nhờ suy luận kiểu ở mức toàn bộ chương trình và sinh mã C
- Pipeline biên dịch dùng parser dựa trên Prism để chuyển Ruby thành văn bản AST, sau đó backend self-hosting thực hiện suy luận kiểu và sinh mã C, rồi dùng trình biên dịch C tiêu chuẩn để tạo binary standalone
- Backend trình biên dịch có cấu trúc self-hosting được viết bằng Ruby, và sau quá trình bootstrap thì
gen2.c == gen3.c được thiết lập, khép kín vòng lặp tự biên dịch lại chính nó
- Bổ sung các tối ưu hóa ở thời điểm biên dịch như làm phẳng nối chuỗi, value-type promotion, loop-invariant length hoisting, static symbol interning, tự động nâng cấp bigint, đồng thời giảm phụ thuộc runtime bên ngoài bằng regexp engine tích hợp, bigint và runtime dạng header đơn
- Không hỗ trợ
eval, metaprogramming, Thread hay xử lý encoding tổng quát, nhưng cho thấy tính thực tiễn của biên dịch Ruby AOT nhờ hình thức phân phối chạy không cần Ruby và chênh lệch hiệu năng lớn trong các workload thiên về tính toán
Cách hoạt động
- Pipeline biên dịch gồm luồng parse file Ruby rồi tuần tự hóa thành tệp văn bản AST, sau đó qua suy luận kiểu và sinh mã C để tạo binary native bằng trình biên dịch C tiêu chuẩn
spinel_parse dùng Prism và libprism để parse Ruby; khi không có binary C thì dùng đường thay thế với CRuby và gem Prism
spinel_codegen chạy như một binary native self-hosted, nhận AST rồi thực hiện suy luận kiểu + sinh mã C
- Bước cuối cùng biên dịch mã nguồn C cùng header runtime bằng
cc -O2 -Ilib -lm, và binary kết quả được tạo ở dạng standalone
Self-Hosting
- Chuỗi bootstrap được khép kín theo cách tạo AST bằng
CRuby + spinel_parse.rb, tạo gen1.c và bin1 bằng CRuby + spinel_codegen.rb, rồi dùng lại binary đã sinh ra để tạo gen2.c, gen3.c
gen2.c == gen3.c xác nhận rằng bootstrap loop đã được khép kín
- Backend
spinel_codegen.rb được viết bằng tập con Ruby mà chính Spinel có thể tự biên dịch
- classes,
def, attr_accessor
if/case/while
each/map/select, yield
begin/rescue
- thao tác String, Array, Hash và File I/O
- Backend không dùng metaprogramming,
eval, require
Hiệu năng và benchmark
- Trạng thái hiện tại là 74 bài test vượt qua, 55 benchmark vượt qua
- Theo 28 benchmark, trung bình nhân nhanh hơn khoảng 11,6 lần so với CRuby
miniruby mới nhất
- Mốc so sánh là bản dựng CRuby
miniruby mới nhất không kèm bundled gem; ngay cả khi so với hệ thống ruby 3.2.3 vốn nhanh hơn, nó vẫn vượt trội trong workload nặng về tính toán
-
Hiệu năng tính toán
life: 20ms so với 1.733ms, nhanh hơn 86,7 lần
ackermann: 5ms so với 374ms, nhanh hơn 74,8 lần
mandelbrot: 25ms so với 1.453ms, nhanh hơn 58,1 lần
- phiên bản đệ quy
fib: 17ms so với 581ms, nhanh hơn 34,2 lần
nqueens: 10ms so với 304ms, nhanh hơn 30,4 lần
tarai: 16ms so với 461ms, nhanh hơn 28,8 lần
tak: 22ms so với 532ms, nhanh hơn 24,2 lần
matmul: 13ms so với 313ms, nhanh hơn 24,1 lần
sudoku: 6ms so với 102ms, nhanh hơn 17,0 lần
partial_sums: 93ms so với 1.498ms, nhanh hơn 16,1 lần
fannkuch: 2ms so với 19ms, nhanh hơn 9,5 lần
sieve: 39ms so với 332ms, nhanh hơn 8,5 lần
fasta: 3ms so với 21ms, nhanh hơn 7,0 lần
-
Cấu trúc dữ liệu và GC
rbtree: 24ms so với 543ms, nhanh hơn 22,6 lần
splay tree: 14ms so với 195ms, nhanh hơn 13,9 lần
huffman: 6ms so với 59ms, nhanh hơn 9,8 lần
so_lists: 76ms so với 410ms, nhanh hơn 5,4 lần
binary_trees: 11ms so với 40ms, nhanh hơn 3,6 lần
linked_list: 136ms so với 388ms, nhanh hơn 2,9 lần
gcbench: 1.845ms so với 3.641ms, nhanh hơn 2,0 lần
-
Chương trình thực tế
json_parse: 39ms so với 394ms, nhanh hơn 10,1 lần
bigint_fib tính số 1000 chữ số: 2ms so với 16ms, nhanh hơn 8,0 lần
ao_render: 417ms so với 3.334ms, nhanh hơn 8,0 lần
pidigits: 2ms so với 13ms, nhanh hơn 6,5 lần
str_concat: 2ms so với 13ms, nhanh hơn 6,5 lần
template engine: 152ms so với 936ms, nhanh hơn 6,2 lần
csv_process: 234ms so với 860ms, nhanh hơn 3,7 lần
io_wordcount: 33ms so với 97ms, nhanh hơn 2,9 lần
Các tính năng Ruby được hỗ trợ
- Ở lớp Core, hỗ trợ classes, inheritance,
super, mixin include, attr_accessor, Struct.new, alias, module constants và open classes cho các kiểu dựng sẵn
- Ở Control Flow, hỗ trợ
if/elsif/else, unless, case/when, pattern matching case/in, while, until, loop, for..in, break, next, return, catch/throw, &.
- Ở Blocks, hỗ trợ
yield, block_given?, &block, proc {}, Proc.new, -> x { }, method(:name), cùng các block method như each, map, select, reduce, sort_by, times, upto, downto
- Ở Exceptions, hỗ trợ
begin/rescue/ensure/retry, raise, và lớp ngoại lệ do người dùng định nghĩa
- Types bao gồm Integer, Float, String, Array, Hash, Range, Time, StringIO, File, Regexp, Bigint, Fiber
- Giá trị đa hình được xử lý bằng tagged unions
- Có nullable object types
T? cho cấu trúc dữ liệu tự tham chiếu
- Global Variables như
$name được biên dịch thành biến C tĩnh, và sai lệch kiểu được phát hiện ngay khi biên dịch
- I/O hỗ trợ
puts, print, printf, p, gets, ARGV, ENV[], File.read/write/open, system(), backtick
Chuỗi, biểu thức chính quy, symbol, Bigint, Fiber
- Strings hỗ trợ cả chuỗi bất biến lẫn có thể thay đổi;
<< tự động nâng cấp thành chuỗi mutable sp_String để append tại chỗ với độ phức tạp O(n)
+, interpolation, tr, ljust/rjust/center và các method chuẩn hoạt động trên cả hai biểu diễn chuỗi
- Các so sánh như
s[i] == "c" được tối ưu để truy cập trực tiếp mảng char và xử lý không cần cấp phát
- Các phép nối như
a + b + c + d được làm phẳng thành một lần gọi sp_str_concat4 hoặc sp_str_concat_arr, giảm N-1 lần cấp phát
str.split(sep) trong vòng lặp tái sử dụng cùng một sp_StrArray, giúp loại bỏ 4 triệu lần cấp phát trong csv_process
- Regexp dùng NFA regexp engine tích hợp, không phụ thuộc bên ngoài
- Hỗ trợ
=~, $1-$9, match?, gsub, sub, scan, split
- Bigint dùng số nguyên độ chính xác tùy ý dựa trên mruby-bigint
- Tự động nâng cấp trong các mẫu như vòng lặp nhân
q = q * k
- Được link như thư viện tĩnh và chỉ được đưa vào khi thực sự dùng
- Fiber cung cấp đồng thời hợp tác dựa trên
ucontext_t
- Hỗ trợ
Fiber.new, Fiber#resume, Fiber.yield và truyền giá trị
- Biến tự do được capture bằng các cell được nâng lên heap
- Symbols được cài đặt bằng kiểu
sp_sym tách biệt với chuỗi
- Giữ nguyên
:a != "a"
- Symbol literal được intern ở thời điểm biên dịch thành hằng
SPS_name
String#to_sym chỉ dùng pool động khi cần
- Hash với khóa symbol dùng
sp_SymIntHash để lưu trực tiếp khóa số nguyên thay vì chuỗi, nên loại bỏ strcmp và cấp phát chuỗi động
Quản lý bộ nhớ và kiểu giá trị
- Quản lý bộ nhớ dùng GC mark-and-sweep, gồm size-segregated free lists, non-recursive marking, sticky mark bits
- Các class nhỏ và đơn giản được tự động nâng cấp thành value types và đặt trên stack
- điều kiện là tối đa 8 trường vô hướng
- không có kế thừa
- không bị thay đổi thông qua tham số
- Cấp phát 1 triệu lần cho class 5 trường giảm từ 85ms xuống còn 2ms
- Chương trình chỉ dùng value types sẽ không xuất kèm runtime GC
Tối ưu hóa
- Thực hiện nhiều tối ưu hóa ở thời điểm biên dịch dựa trên suy luận kiểu toàn bộ chương trình
- Value-type promotion biến các class nhỏ bất biến thành đối tượng stack dạng C struct, loại bỏ overhead GC
- Constant propagation inline trực tiếp các hằng literal đơn giản như
N = 100 vào nơi sử dụng thay vì truy vấn cst_N
- Loop-invariant length hoisting chỉ tính độ dài một lần trước vòng lặp cho các biểu thức như
while i < arr.length
- Nếu phần thân thay đổi đối tượng nhận, như
arr.push, tối ưu này sẽ bị tắt
- Method inlining gắn
static inline cho các method ngắn, không đệ quy, tối đa 3 câu lệnh để khuyến khích gcc inline
- String concat chain flattening rút chuỗi nối thành một lời gọi duy nhất, loại bỏ việc tạo chuỗi trung gian
- Bigint auto-promotion tự động nâng các mẫu cộng tự tham chiếu hoặc nhân lặp sang bigint
- Bigint
to_s dùng mpz_get_str của mruby-bigint để xử lý theo kiểu divide-and-conquer O(n log²n)
- Static symbol interning biến
"literal".to_sym thành hằng thời điểm biên dịch SPS_<name>; chỉ thêm pool runtime khi dùng interning động
- Trong
sub_range, chuỗi có độ dài đã được hoist dùng sp_str_sub_range_len để bỏ qua lời gọi strlen nội bộ
line.split(",") trong vòng lặp tái sử dụng sp_StrArray hiện có
- Dead-code elimination dùng
-ffunction-sections -fdata-sections và --gc-sections để loại bỏ hàm runtime không dùng khỏi binary cuối
- Iterative inference early exit dừng ngay vòng lặp tìm điểm cố định khi 3 mảng chữ ký của param, return, ivar không còn thay đổi
- Phần lớn chương trình hội tụ sau 1–2 vòng thay vì 4 vòng đầy đủ
- Thời gian bootstrap giảm khoảng 14%
parse_id_list byte walk thay parser danh sách trường AST được gọi khoảng 120 nghìn lần trong quá trình tự biên dịch từ s.split(",") sang duyệt thủ công s.bytes[i], giảm số lần cấp phát mỗi lần gọi từ N+1 xuống còn 2
- Mã C được sinh ra giữ warning-free build ở mức cảnh báo mặc định, và harness dùng
-Werror để lộ hồi quy ngay lập tức
Kiến trúc
- Cấu trúc kho mã được chia thành các thành phần sau
spinel: script wrapper một lệnh dựa trên POSIX shell
spinel_parse.c: frontend C 1.061 dòng từ libprism sang AST văn bản
spinel_codegen.rb: backend compiler 21.109 dòng từ AST sang mã C
lib/sp_runtime.h: header thư viện runtime 581 dòng
lib/sp_bigint.c: số nguyên độ chính xác tùy ý 5.394 dòng
lib/regexp/: regexp engine tích hợp 1.759 dòng
test/: 74 bài test chức năng
benchmark/: 55 benchmark
Makefile: tự động hóa build
- Runtime
lib/sp_runtime.h chứa GC, cài đặt array/hash/string và các hỗ trợ runtime khác trong một tệp header duy nhất
- Mã C sinh ra include header này, còn linker chỉ lấy phần cần thiết từ
libspinel_rt.a
- Parser có hai cách triển khai
spinel_parse.c link trực tiếp libprism để chạy không cần CRuby
spinel_parse.rb là fallback CRuby dùng gem Prism
- Cả hai parser tạo ra cùng một đầu ra AST, và wrapper
spinel sẽ ưu tiên binary C nếu có thể
require_relative được giải quyết ở thời điểm parse để inline các tệp được tham chiếu
Hạn chế
- No eval: không hỗ trợ
eval, instance_eval, class_eval
- No metaprogramming: không hỗ trợ
send, method_missing, define_method động
- No threads: không hỗ trợ
Thread, Mutex, chỉ hỗ trợ Fiber
- No encoding: giả định UTF-8 và ASCII
- No general lambda calculus: không xử lý
-> x { } lồng sâu và lời gọi []
Phụ thuộc và mô hình thực thi
- Phụ thuộc lúc build là thư viện C libprism và CRuby cho bootstrap ban đầu
- Không có phụ thuộc runtime; binary sinh ra chỉ cần libc + libm
- Regexp dùng engine tích hợp nên không cần thư viện ngoài
- Bigint được tích hợp sẵn nhưng chỉ link khi thực sự dùng
- Prism là parser Ruby mà
spinel_parse sử dụng
make deps tải tarball gem prism từ rubygems.org và giải nén mã C vào vendor/prism
- Nếu prism gem đã được cài, hệ thống sẽ tự phát hiện
- Cũng có thể chỉ định đường dẫn tùy chỉnh bằng
PRISM_DIR=/path/to/prism
- CRuby chỉ cần cho bootstrap ban đầu; sau
make, toàn bộ pipeline chạy không cần Ruby
Lịch sử dự án
- Spinel ban đầu được triển khai bằng C, quy mô 18K lines, và vẫn còn trong nhánh
c-version
- Sau đó dự án đi qua nhánh
ruby-v1, được viết lại bằng Ruby
master hiện tại là phiên bản được viết lại bằng tập con Ruby có thể self-hosting
Giấy phép
- Sử dụng MIT License
- Tuân theo tệp LICENSE
1 bình luận
Ý kiến trên Hacker News
Nếu là thứ do Matz làm thì hẳn ông ấy cũng hiểu rất rõ những giới hạn của Ruby semantics, nên tạo được cảm giác tin cậy
Luận văn thạc sĩ của tôi cũng là về AOT JS compiler, chạy được thật nhưng bị ràng buộc dữ liệu đầu vào quá lớn nên cuối cùng phải bỏ dở
Hồi đó các lập trình viên JS chưa quen với việc tự giác tuân thủ những ràng buộc như vậy, và các đầu vào vốn dĩ không thể biết trước như
JSON.parselà trở ngại lớnBây giờ nhờ TypeScript nên có thể thực tế hơn rất nhiều so với khi đó
Chỉ nhìn vào lambda calculus nói chung cũng thấy giới hạn của suy luận kiểu là rất rõ ràng, và các bài báo phía Matt Might hay dự án Shed-skin Python cũng bộc lộ những ràng buộc tương tự
Tôi tò mò
eval,send,method_missing,define_methodthực sự phổ biến đến mức nào trong mã Ruby ngoài đời, và cũng tò mò các đầu vào parse không kiểu, ví dụ JSON input, thường được xử lý ra saoViệc parse Ruby khó đến mức còn khó hơn cả khâu biên dịch, nên họ dùng Prism, rồi sinh ra mã C
Bản thân việc hiện thực các Ruby semantics cơ bản thì không hẳn khó đến vậy
Ngược lại, tôi đang vật lộn với một self-hosting AOT compiler cũ viết bằng Ruby thuần, vì cố chấp tự làm parser riêng nên đã tự chọn con đường khó hơn nhiều
Tôi học được khá sớm rằng 80% đầu có thể làm tương đối sơ sài mà vẫn chạy được phần lớn mã Ruby, còn “80% thứ hai” mới thực sự khó thì lại tập trung ở những thứ Matz đã bỏ ra khỏi dự án này và khỏi mruby, như encoding hay đủ loại tính năng phụ trợ
Nói thật là trong Ruby có không ít tính năng mà tôi chưa từng thấy một lần nào trong mã thực tế, nên nếu vài cái bị deprecated tôi cũng không thấy lạ
send,method_missing,define_methodthì rất phổ biếnCác ràng buộc thì tương tự mruby, nhưng ngay cả dưới các ràng buộc đó vẫn có chỗ để dùng
Hỗ trợ
send,method_missing,define_methodtương đối dễCòn hỗ trợ eval() thì cực kỳ đau đầu
Tuy vậy, một tỷ lệ lớn
eval()trong Ruby có thể được quy về phiên bản block của instance_eval theo cách tĩnh, nên trong những trường hợp đó AOT compile khá dễVí dụ nếu chuỗi truyền vào
eval()có thể biết trước hoặc phân rã được một cách tĩnh thì khả năng giải quyết sẽ lớnTrên thực tế, nhiều cách dùng
eval()là không cần thiết hoặc chỉ gần như cách né introspection đơn giản, nên có thể xử lý bằng kiểm tra tĩnhCompiler của tôi cũng định nếu chỗ đó trở thành nút thắt thì sẽ đụng vào từ đó trước
Việc ingest JSON không kiểu cũng có lẽ sẽ dùng những cơ chế như vậy
Nếu bỏ chúng đi thì sẽ còn lại một ngôn ngữ nhỏ, dễ đọc, không có type mạnh như Crystal nhưng cũng không dựa vào metaprogramming nhiều như Ruby chính thức
Vì thế tiềm năng có vẻ khá lớn, nhưng rốt cuộc vẫn phải chờ thời gian mới biết được
evalkhá thường xuyênCó thể không dùng cũng được, nhưng với tôi như vậy ergonomic hơn
eval,exec,define_method, và pattern tạo class mới bằngClass.new,Struct.newPhần lớn việc dùng chúng tập trung vào thời điểm boot của app hoặc trong lúc require file, nên ở một khía cạnh nào đó nó đã khá giống giai đoạn compile rồi
Đây là thứ Matz vừa trình bày tại RubyKaigi 2026
Dù còn mang tính thử nghiệm, ông ấy đã làm ra nó trong khoảng một tháng với sự trợ giúp của Claude, và demo trực tiếp cũng thành công
Tên gọi được lấy từ con mèo mới của Matz, còn tên con mèo thì bắt nguồn từ tên mèo trong Card Captor Sakura, nơi nó lại ghép cặp với một nhân vật tên là Ruby
Với người như Matz thì có khi là đẩy từ 100x lên 500x
https://en.wikipedia.org/wiki/Spinel
Có vẻ video vẫn chưa phát trực tiếp, và hình như đang được đăng dần từng cái lên kênh này
https://www.youtube.com/@rubykaigi4884/videos
Tên dự án cũng tạo cảm giác như được đặt theo cảm xúc
Rõ ràng là rất ấn tượng, nhưng trông có vẻ không thể bảo trì nếu không có AI agent
spinel_codegen.rbdài 21 nghìn dòng, có method lồng tới 15 cấpVốn dĩ mã compiler đã khó mà đẹp, nhưng ngay cả theo tiêu chuẩn đó thì cái này cũng có vẻ rất khó để con người quản lý
Compiler có ranh giới subsystem rõ ràng và handoff giữa các giai đoạn cũng mạch lạc, nên thực ra lại thuộc nhóm dễ modular hóa nhất
Vấn đề thường là sau khi đã làm cho nó chạy được thì không còn thời gian refactor, và thế là sự bừa bộn cứ phình ra
spinel_codegen.rbgần như ở mức eldritch horrorDùng Claude thì tôi cũng luôn ra kiểu spaghetti code thế này, nên từng tự hỏi không biết mình đang làm sai gì
Nhưng nhìn thấy cả trong một dự án thực sự thú vị do người mà tôi xem là lập trình viên top đầu tạo ra, chất lượng mã ở nhiều chỗ cũng khá tệ, thì hóa ra không phải chỉ mình tôi
Ví dụ
infer_comparison_type()chưa phải ca tệ nhất và cũng không khó đọc, nhưng vẫn có cách hiện thực đơn giản và rõ ràng hơn nhiều mà Claude lại không đi tới đượcNếu gom các toán tử so sánh vào
Setrồi xử lý bằnginclude?thì sẽ ngắn hơn, nhanh hơn, dễ đọc hơn và dễ bảo trì hơnThế mà Claude lúc nào cũng trôi về kiểu chuỗi if-return, thậm chí còn có cảm giác nó lạ lẫm cả với if-else
Codebase do Claude viết của tôi cũng đầy những pattern như vậy, nên giờ tôi biết không chỉ mình mình gặp thế
Ngược lại, các file khác tốt hơn nhiều, đặc biệt là thư mục
libcó vẻ tương ứng với thư mụcexttrong repo Ruby chính và chất lượng khá ổnAPI cũng rõ ràng chịu ảnh hưởng từ MRI Ruby, và dù phần hiện thực khác khá nhiều, có vẻ Matz đã hướng nó mô phỏng một phần API gốc nên đầu ra trông gọn gàng hơn
[1] https://github.com/matz/spinel/blob/98d1179670e4d6486bbd1547...
Chỉ cần test và benchmark qua là tạm ổn rồi
Tuy vậy, tôi vẫn nghi ngờ liệu file khổng lồ như vậy có thật sự dễ cho AI xử lý hay không
Tôi đang cố giới hạn file trong khoảng dưới 300 dòng, và nghĩ rằng mã dễ hiểu với con người thì cũng sẽ dễ cho coding agents
Các ràng buộc được nói là như sau
No eval:
eval,instance_eval,class_evalNo metaprogramming:
send,method_missing,define_method(động)No threads:
Thread,Mutex(có hỗ trợ Fiber)No encoding: giả định UTF-8/ASCII
No general lambda calculus:
-> x { }lồng sâu kèm lời gọi[]Riêng giả định UTF-8/ASCII thì cá nhân tôi không thấy là ràng buộc lớn, nhưng phần còn lại có vẻ sẽ là hạn chế thực sự với khá nhiều chương trình
Và có vẻ sẽ cần rất nhiều công sức nếu muốn đưa các phần đó trở lại
Tôi đã dùng Ruby rất lâu, và với tư cách người từng dùng hết tất cả những tính năng được liệt kê, thứ mà sau cả quá trình tiến hóa tôi lại muốn chính là phiên bản Ruby đơn giản như thế này
Nó đơn giản hơn, dễ hiểu hơn mà vẫn giữ được chất thẩm mỹ rất Ruby
Giờ nhờ LLM mà năng suất sinh code đã cao đến mức không còn cần phải dùng metaprogramming để cắt boilerplate vì năng suất lập trình viên như trước nữa
Bởi vì tỷ lệ lập trình viên trực tiếp tự viết code đang giảm đi
Cú pháp tương tự và có static type system, từ đó dẫn tới mã biên dịch hiệu quả hơn
evalthì tôi còn thấy tốt hơn, nhưng đến cả threads và mutexes cũng không có thì hơi tiếcViệc thiếu
define_methodthì xét theo công dụng của nó tôi còn hiểu đượcNhưng
sendvàmethod_missinglại rất phổ biến trong các thư viện hiện có, và cách hiện thực cũng có vẻ không đến mức quá khó, kiểu dựng bảng tra cứu trong bộ nhớ ngay lúc compileNên tôi không rõ đây là cố ý bỏ đi, hay chỉ là chưa làm tới đó
Tôi mong là vế sau, nhưng ít nhất ở thời điểm hiện tại thì vì vấn đề tương thích nên có lẽ khó đem vào thực chiến
Mà là giảm lượng code phải đọc
Cái này thật sự rất ngầu, và tôi đã chờ một AOT compiler cho Ruby từ lâu
Chỉ tiếc là không có fallback cho
evalhay metaprogramming, nhưng có vẻ họ làm vậy để tập trung vào một subset nhỏ mà hiệu năng caoTôi hy vọng gem tạo bằng AOT compiler này có thể tương tác tốt với MRI
Việc đóng gói hoặc bundle Ruby chuẩn và gem vẫn cần tebako, kompo, ocran, và trước đây cũng từng có các dự án như ruby-packer, traveling ruby, jruby warbler
Có thêm một lựa chọn nữa thì tốt, nhưng tôi vẫn mong sẽ có phiên bản quyết định cuối cùng với UX cho lập trình viên tốt hơn
Vì nó đã quá lâu không được cập nhật
Tôi thắc mắc vì sao lại no threads
Ruby scheduler và phần hiện thực pthread phía dưới có vẻ như vẫn có thể hoạt động ổn ngay cả trong vùng C, nên tôi tự hỏi có phải họ nhắm tới zero dependency không
Nếu không phải là dự định thêm optional extension sau này hay chỉ là tạm thời chưa làm, thì lựa chọn này thấy hơi lạ
Có lẽ chỉ là chưa làm tới đó thôi
Multithreading vốn đã cực khó để làm cho đúng
Việc làm ra nó chỉ trong hơn một tháng thật đáng kinh ngạc
Dù có nói gì về AI đi nữa thì khi rơi vào tay lập trình viên giỏi, nó đúng là tạo ra mức tăng tốc khủng khiếp
Còn Matz thì có cảm giác chỉ cần
gem env|infovớifindlà đủVì đây là thứ do Matz làm, tôi tò mò khả năng thực tế để nó trở thành một phần của Ruby core trong tương lai là bao nhiêu
Và nếu vậy thì nó sẽ đe dọa Crystal đến mức nào
Những đặc tính như vậy gần như thiết yếu để compile và bảo trì các chương trình lớn
Còn cái này chỉ là subset Ruby bị giới hạn, nên đa số gem Ruby phổ biến có lẽ sẽ không chạy nguyên trạng
Xét ở góc độ là một subset ngôn ngữ nhắm tới biên dịch C, nó có vẻ gần với PreScheme hơn
Ở giai đoạn hiện tại tôi không nghĩ hai bên đang cạnh tranh trực tiếp trong cùng một không gian
Ruby đầy đủ gần như chắc chắn vẫn sẽ cần JIT
[1]: https://prescheme.org/
Kiểu như màn báo thù của Rational Unified Process và các công cụ như Enterprise Architect
Khác biệt chỉ là thay vì UML diagram thì giờ thứ được đưa ra là file markdown
Cái này có vẻ sẽ hữu ích trong mảng infrastructure tools
Ví dụ có thể hình dung ra một bundler viết bằng Ruby nhưng được compile tĩnh, nên đồng thời kiêm luôn vai trò công cụ cài Ruby kiểu RVM
Buildpack Ruby hiện tại cũng viết bằng Ruby, nhưng phải bootstrap bằng bash nên rất phiền và sinh ra edge case
CNB được viết bằng Rust để tránh vấn đề đó, và ý tưởng phát hành một binary duy nhất không phụ thuộc gì thật sự rất mạnh