1 điểm bởi GN⁺ 2026-04-25 | 1 bình luận | Chia sẻ qua WhatsApp
  • Trình biên dịch AOT chuyển mã nguồn Ruby thành mã C sau khi thực hiện suy luận kiểu cho toàn bộ chương trình, rồi tạo ra binary native độc lập
  • Được chính matz, cha đẻ của Ruby, trực tiếp phát triển; phần backend của trình biên dịch cũng được viết bằng Ruby, theo cấu trúc self-hosting tự biên dịch chính nó
  • Hiệu năng nhanh hơn khoảng 11,6 lần so với miniruby (Ruby 4.1.0dev); Conway's Game of Life nhanh hơn 86,7 lần, ackermann 74,8 lần, mandelbrot 58,1 lần
  • 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
  • Hỗ trợ rộng rãi nhiều tính năng của Ruby như class, kế thừa, block, xử lý ngoại lệ, Fiber, engine Regexp NFA tích hợp, Bigint tự động nâng cấp, pattern matching
  • Các class nhỏ có từ 8 trường scalar trở xuống được tự động cấp phát trên stack dưới dạng value type, loại bỏ hoàn toàn overhead của GC (1 triệu lần cấp phát: 85ms → 2ms)
  • Chuỗi nối a + b + c + d được làm phẳng bằng một lần malloc duy nhất; split trong vòng lặp sẽ tái sử dụng sp_StrArray để loại bỏ các lần cấp phát không cần thiết
  • Nhiều tối ưu hóa ở thời điểm biên dịch như hoisting độ dài bất biến trong vòng lặp, truyền hằng số, tự động inline các phương thức có không quá 3 câu lệnh, dừng sớm suy luận lặp (~giảm 14% thời gian bootstrap)
  • Binary được tạo ra không có phụ thuộc runtime, có thể chạy chỉ với libc + libm
  • Không hỗ trợ eval, metaprogramming, Thread và Mutex, v.v. (chỉ hỗ trợ Fiber)
  • Giấy phép MIT

1 bình luận

 
GN⁺ 2026-04-25
Ý 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.parse là trở ngại lớn
    Bâ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_method thự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 sao

    • Thiết kế này trông khá pragmatic
      Việ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_method thì rất phổ biến
      Cá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_method tươ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ớn
      Trê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ĩnh
      Compiler 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
    • Cần khá nhiều tính năng kiểu này mới tạo ra được Rails-style magic
      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
    • Nếu là cách compile Ruby sang Objective-C thì có vẻ sẽ vừa hỗ trợ được toàn bộ tính năng Ruby vừa nhanh hơn Ruby interpreter
    • Tôi thuộc phe dùng eval khá thường xuyên
      Có thể không dùng cũng được, nhưng với tôi như vậy ergonomic hơn
    • Theo kinh nghiệm của tôi, cái thú vị là eval, exec, define_method, và pattern tạo class mới bằng Class.new, Struct.new
      Phầ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

    • Nhiều người hay nói AI sẽ tự làm cả chương trình từ đầu đến cuối, nhưng tôi nghĩ kịch bản thực tế hơn là biến 10x programmer thành 100x programmer
      Với người như Matz thì có khi là đẩy từ 100x lên 500x
    • Trong đầu tôi, Spinel gần đây nhất là nhân vật bên Steven Universe, nên hoàn toàn không nhận ra trò chơi chữ Spinel/Ruby (Moon), nhưng biết rồi thì thấy cả ngày vui hơn hẳn
    • Tôi thì đương nhiên tưởng là đang nói đến khoáng vật spinel :)
      https://en.wikipedia.org/wiki/Spinel
    • Cảm ơn
      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
    • Câu chuyện về nguồn gốc tên con mèo đó nghe khá đáng ngờ nếu xét tới Ruby Central drama và mối quan hệ với các nhà sáng lập Spinel.coop
      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.rb dài 21 nghìn dòng, có method lồng tới 15 cấp
    Vố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ý

    • Mã compiler nếu có thời gian thì hoàn toàn có thể làm cho đẹp
      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.rb gần như ở mức eldritch horror
      Dù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 được
      Nếu gom các toán tử so sánh vào Set rồi xử lý bằng include? thì sẽ ngắn hơn, nhanh hơn, dễ đọc hơn và dễ bảo trì hơn
      Thế 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 lib có vẻ tương ứng với thư mục ext trong repo Ruby chính và chất lượng khá ổn
      API 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...
    • Ở giai đoạn hiện tại, tôi không nghĩ việc con người có thể tự tay bảo trì nó quan trọng đến thế
      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_eval
    No 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

    • Vậy là khá nhiều phần magic của Ruby biến mất
  • 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

    • Nếu thứ bạn muốn chỉ là Ruby aesthetic thì Crystal cũng có thể rất hợp
      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
    • Không có eval thì 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ếc
      Việc thiếu define_method thì xét theo công dụng của nó tôi còn hiểu được
      Nhưng sendmethod_missing lạ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 compile
      Nê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
    • Ưu điểm của metaprogramming vốn không phải là viết ít code hơ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 eval hay metaprogramming, nhưng có vẻ họ làm vậy để tập trung vào một subset nhỏ mà hiệu năng cao
    Tô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

    • Đúng vậy, gần đây tôi cũng phải fork warbler
      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ạ

    • Tôi vẫn chưa thấy bằng chứng nào cho thấy họ đã cố ý quyết định không hỗ trợ cái này
      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ả ngành thì bắt đầu bằng việc dựng đủ thứ như agent harness, SOUL.md, phân quyền, skills, MCPs, hooks, env
      Còn Matz thì có cảm giác chỉ cần gem env|info với find là đủ
  • 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

    • Crystal có static type system rõ ràng và được tối ưu cho AOT compile ngay từ cấp độ ngôn ngữ
      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/
    • Theo một góc nhìn khác, rốt cuộc LLM có lẽ sẽ tiến tới điểm có thể tuôn ra formal specification cho bất kỳ ngôn ngữ nào ta muốn
      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