Ruby 3.3 được phát hành
(ruby-lang.org)- YJIT cải thiện đáng kể hiệu năng và mức sử dụng bộ nhớ so với Ruby 3.2, và nhanh hơn trình thông dịch hơn 3 lần trong Optcarrot
- Code GC của YJIT mặc định bị vô hiệu hóa, và
--yjit-exec-mem-sizehoạt động như một giới hạn cứng khiến việc biên dịch mã mới dừng lại - Bổ sung
RubyVM::YJIT.enable, cho phép kích hoạt YJIT trong runtime mà không cần thay đổi tham số dòng lệnh hoặc biến môi trường - Trình phân tích cú pháp Prism được thêm dưới dạng gem mặc định, có thể dùng các API
Prism.parse(source),Prism.parse_comments(source),Prism.parse_success?(source) - Có thể thử nghiệm compiler Prism bằng
ruby --parser=prismhoặcRUBYOPT="--parser=prism", nhưng cờ này chỉ dành cho mục đích gỡ lỗi - Trình tạo parser được thay từ Bison sang Lrama, và parser nội bộ của Lrama được thay bằng LR parser do Racc tạo ra để dễ bảo trì hơn
- Compiler JIT thuần Ruby RJIT thay thế MJIT, nhưng chỉ hỗ trợ kiến trúc x86-64 trên Unix và chỉ giới hạn cho mục đích thử nghiệm
- M:N thread scheduler được đưa vào, trong đó N luồng native quản lý M luồng Ruby, nhưng vì có thể phá vỡ khả năng tương thích với các C extension nên mặc định bị vô hiệu hóa trong main Ractor
- Cách dùng
itkhi được gọi không có đối số và trong một block không có tham số thông thường sẽ bị ngừng hỗ trợ (deprecation), và trong Ruby 3.4 dự kiến sẽ trở thành tham chiếu đến tham số block đầu tiên Regexp::newchỉ cho phép tối đa 2 đối số, thay cho cách gọi 3 đối số đã bị ngừng hỗ trợ từ Ruby 3.2ext/readlineđược cho nghỉ hưu, và trong tương lai sẽ phụ thuộc vàoreline, một triển khai thuần Ruby tương thích với APIext/readline- Nếu cần
ext/readline, có thể cài đặt từ rubygems.org bằnggem install readline-ext, và không còn cần cài các thư viện nhưlibreadlinehoặclibedit - RubyGems và Bundler sẽ cảnh báo nếu
requiremột số gem mà không thêm chúng vào Gemfile hoặc gemspec; các gem này dự kiến sẽ trở thành bundled gem trong các phiên bản Ruby tương lai - Khi dùng gem bootsnap, cảnh báo này sẽ bị chặn; do hạn chế của phiên bản này, khuyến nghị chạy ứng dụng ít nhất một lần với biến môi trường
DISABLE_BOOTSNAP=1 prism 0.19.0được thêm làm gem mặc định, vàracc 1.7.3được nâng từ default gem lên bundled gem
1 bình luận
Ý kiến trên Hacker News
Tôi cho rằng với Ruby 3.3, Ruby đã thực sự trở lại mạnh mẽ. Đây là ngôn ngữ tập trung vào hạnh phúc của lập trình viên nhưng từng bị chế giễu là chậm, còn giờ thì không còn chậm nữa
YJIT là một công nghệ đáng kinh ngạc, và cùng với object shape cùng nhiều tối ưu hóa garbage collection khác, Ruby đang trở nên khá nhanh. Những nơi dùng Ruby ở quy mô lớn như Shopify cũng đã bật YJIT trên bản pre-release 3.3 để chạy thực tế và báo cáo mức cải thiện hiệu năng ở mức hai chữ số
Cá nhân tôi thật sự rất háo hức với Ruby và tương lai của nó, và muốn thử làm việc với Ruby 3.3 rồi áp dụng vào các site production của khách hàng
https://railsatscale.com/2023-09-18-ruby-3-3-s-yjit-runs-sho...
Tôi còn dùng nó làm lớp mã glue giữa kho lưu trữ bản ghi DNS dựa trên Redis và PowerDNS, và cả stack đó xử lý 500 triệu truy vấn mỗi tháng trên 14 VPS nhỏ mà nhìn trên htop gần như chẳng thấy gì. Tôi dùng PowerDNS không phải vì hiệu năng, mà vì tự triển khai những thứ như crypto, HTTP, DNS để lộ ra Internet công cộng thường không phải ý hay
Điều trớ trêu của web hiện đại là ứng dụng web làm bằng Ruby “chậm” và server-side rendering thực tế lại tải trang nhanh hơn cơ sở dữ liệu eventual consistency chậm chạp cùng các frontend web app phình to. Trên web hiện đại, tôi thấy spinner tải ngay cả với những việc rất nhỏ quá thường xuyên
Bấm vào link thì hóa ra là mức cải thiện hơn 10%. Có vẻ điều này không thay đổi được nhiều nhận thức rằng Ruby chậm hơn khoảng 50 đến 200 lần so với các ngôn ngữ “nhanh” như Rust, Java, Go, C++
Ruby 3.3 có vẻ là một trong những bản phát hành Ruby quan trọng và nhiều tính năng nhất trong 10 năm qua. Tôi không ngờ Ruby lại tung ra JIT sẵn sàng cho production trước cả Python, rồi còn có Prism, Lrama và IRB
Nhưng những thứ chưa được bàn tới đủ nhiều là Ractor, bộ lập lịch luồng M:N, Fiber và Async. Đặc biệt trong bối cảnh Rails, tôi muốn nghe ý kiến xem có ai đang dùng các tính năng này trong môi trường production không
Dù vậy, Ractor xứng đáng được chú ý hơn. Đây là một tính năng cực lớn
Có lẽ trong nội bộ các công ty đang tồn tại hàng nghìn giải pháp tùy biến riêng dựa trên RabbitMQ hoặc Redis
Cứ đều đặn như đồng hồ, Ruby Lang lại phát hành bản mới vào mỗi dịp Giáng Sinh
Đã có thể dùng trên Heroku: https://devcenter.heroku.com/changelog-items/2772
Trông rất ổn. IRB mới là một trình thông dịch Ruby tương tác với khả năng tự động hoàn thành và gỡ lỗi tốt hơn. Có vẻ phần lớn thay đổi trong Ruby 3.3 sẽ dẫn tới việc cải thiện công cụ cho lập trình viên
API của ngôn ngữ nhìn chung vẫn được giữ nhất quán với các bản phát hành trước. Tôi đã viết hướng dẫn cập nhật Ruby 3.3 kèm ghi chú cho nhiều trình quản lý phiên bản khác nhau: https://mac.install.guide/ruby/update.html
Tôi khá tò mò không biết nên khuyên dùng trình quản lý phiên bản nào. Trước đây tôi từng khuyên dùng asdf, frum, chruby
Giờ có thể ngắt phân giải tên như
Socket.getaddrinfo, và họ nói rằng mỗi khi cần phân giải tên thì sẽ tạo một worker pthread để chạygetaddrinfo(3)trong đóTôi tò mò không biết các runtime ngôn ngữ khác có làm tương tự không. Việc tạo thread nghe có vẻ quá nặng, nhưng trên thực tế có thể không phải vấn đề lớn. Ngay cả theo benchmark riêng của họ thì overhead cũng nhỏ chứ không phải bằng 0
10000.times { Addrinfo.getaddrinfo("www.ruby-lang.org", 80) }mất 2,3 giây trước bản vá và 3,0 giây sau bản vá, còn100.times { URI.open("https://www.ruby-lang.org").read }mất 3,36 giây trước bản vá và 3,40 giây sau bản váKhông giống như Python, nơi cùng một thao tác được triển khai lại với “màu” async, tôi có cảm giác mọi thứ ở đây mặc định đều được chuyển sang bất đồng bộ, nhưng không chắc mình hiểu đúng
Nếu đã biết Python và NodeJS thì băn khoăn liệu có đáng học Ruby hay không. Ruby thú vị nhưng tạo cảm giác khó
Nếu đã thành thạo Node và Python thì học cũng khá dễ. Điểm trừ là nếu đã biết các ngôn ngữ đó rồi thì Ruby không thực sự mang lại điều gì mới mẻ về bản chất. Điểm cộng chủ yếu nằm ở tính thẩm mỹ: Ruby đưa ra và khuyến khích những cách diễn đạt mã nguồn thực sự đẹp, và trải nghiệm đó rất thú vị
Tôi chủ yếu làm việc trong codebase TypeScript, nhưng khi xử lý dữ liệu log hay văn bản bán cấu trúc, hoặc khi cần rewrite dựa trên regex trên nhiều file, tôi thường lôi Ruby ra dùng. Ruby rất vui, và có lẽ là ngôn ngữ vui nhất trong số những ngôn ngữ tôi đã dùng thường xuyên, nên bản thân điều đó đã là phần thưởng rồi
Ví dụ lớn nhất là Ruby thực sự rất thích block. Chúng có mặt khắp thư viện chuẩn, có rất nhiều cú pháp rút gọn, và cũng có vô số DSL xoay quanh block. Các tính năng hàm chức năng tiêu chuẩn cũng đã có trong thư viện chuẩn từ lâu, nên có thể viết theo phong cách functional một cách mượt mà và dễ đọc
Về mặt kỹ thuật thì trong Python hầu hết cũng làm được, nhưng khi viết và đọc trông gượng gạo hơn nhiều. Python có lambda, nhưng có cảm giác ngôn ngữ này không thực sự thích lambda cho những thứ vượt quá các mục đích vụn vặt, và thay vào đó hàm được dùng như giá trị hạng nhất ở khắp nơi
Những người nhạy với công nghệ mới lúc đó đang chuyển sang phát triển API-oriented dựa trên node.js và AngularJS, nhanh hơn rất nhiều so với những gì làm bằng RoR. RoR năm 2013 vẫn chủ yếu theo kiểu monolithic tiêu chuẩn, và trông đã bắt đầu cũ đi khi không chuyển đổi tốt sang mô hình mới là tách frontend/backend
Lý do tôi nói dài về framework làm bằng Ruby chứ không phải bản thân Ruby là vì ngay cả bây giờ, tôi đoán 95% phát triển Ruby vẫn là ứng dụng Rails. Ruby nổi tiếng phần lớn là nhờ Ruby on Rails, và nếu RoR đang đi xuống thì Ruby có lẽ cũng sẽ đi theo quỹ đạo đó cho đến khi co lại thành một cộng đồng nhỏ nhưng nhiệt huyết như Perl
Chỉ xét riêng ngôn ngữ thì tôi không nghĩ ra lý do gì để chọn Ruby thay vì Python hay TypeScript. Dù xét về ngôn ngữ hay nền tảng, Ruby có vẻ không có điểm nào làm tốt hơn các đối thủ vốn đã đứng vững hơn
Prism khá thú vị. Tôi tò mò không biết đã có công cụ phân tích mã Ruby nào dùng nó chưa. Tôi đang tìm cách phân tích code của công ty
Biến môi trường
RUBY_MAX_CPU=nđược cho là đặt tối đa N, tức số lượng native thread tối đa, và mặc định là 8Tôi nghĩ mặc định nên là số lõi logic, giống như Tokio của Rust hay vô số runtime M:N khác
init()hoặcmain()Tôi hy vọng Ruby 4.0 sẽ cho phép import tường minh thay vì cách hiện tại là nạp gem một cách ngầm định vào global namespace
Cũng có thảo luận về tính năng “namespace on read” vẫn đang ở giai đoạn suy đoán: https://bugs.ruby-lang.org/issues/19744
Việc global namespace chỉ hỗ trợ đúng một phiên bản cho mỗi gem cũng khuyến khích một văn hóa lành mạnh coi trọng ABI ổn định và thời gian đệm trước khi loại bỏ. So với một số hệ sinh thái ngôn ngữ khác thì đúng là như mơ
Hoặc cũng có thể tôi đang nói hoàn toàn sai
https://youtu.be/4MM5b2F9zrM?si=UT3aUbD6p_uBZehS&t=2347