1 điểm bởi GN⁺ 2023-12-26 | 1 bình luận | Chia sẻ qua WhatsApp
  • 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-size hoạ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=prism hoặc RUBYOPT="--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 it khi đượ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::new chỉ 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.2
  • ext/readline được cho nghỉ hưu, và trong tương lai sẽ phụ thuộc vào reline, một triển khai thuần Ruby tương thích với API ext/readline
  • Nếu cần ext/readline, có thể cài đặt từ rubygems.org bằng gem install readline-ext, và không còn cần cài các thư viện như libreadline hoặc libedit
  • RubyGems và Bundler sẽ cảnh báo nếu require mộ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

 
GN⁺ 2023-12-26
Ý 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...

    • Chút cải thiện hiệu năng có lẽ chưa khiến tôi chọn Ruby cho dự án mới, nhưng việc cải thiện dần dần vẫn rất đáng mừng. Lo lắng quá mức về hiệu năng gần như luôn là tối ưu hóa quá sớm, và Ruby từ trước tới nay vẫn đủ nhanh cho những gì tôi cần
      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ản thân ngôn ngữ Ruby có thể nhanh, nhưng toàn bộ hệ sinh thái thì chậm đến mức đau đớn. Nếu dùng Rails để làm một server mà mỗi request đi qua truy vấn cơ sở dữ liệu và gọi các dịch vụ khác rồi trả về 1MB JSON, tôi chỉ đạt khoảng 100 request/giây; viết lại cùng dịch vụ đó bằng Go thì xử lý được 100.000 request/giây
    • Tôi từng thắc mắc liệu “cải thiện hiệu năng hai chữ số” nghĩa là nhanh hơn 10%, hay nhanh gấp 10 lầ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++
    • Một lĩnh vực mà Ruby có thể cải thiện trải nghiệm lập trình viên là trải nghiệm gỡ lỗi tốt hơn. Có lẽ vì tôi đã quá quen với Chrome DevTools, nhưng lần gần nhất debug mã Ruby dùng nhiều metaprogramming, việc hiểu chuyện gì đang xảy ra thực sự rất khổ sở
    • Nghe cụm “hai chữ số” tôi đã kỳ vọng 50% hay 80%, nhưng mở link ra thì là 13~15%
  • 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

    • Việc Ruby ra JIT sẵn sàng cho production trước Python là điều hoàn toàn có thể đoán trước. Ruby không có một cộng đồng tính toán khoa học khổng lồ phụ thuộc vào chi tiết triển khai của từng interpreter như Python
    • Tôi không rõ Ruby 3.3 có thực sự là bản phát hành quan trọng đến vậy không. Tôi không thấy điều gì khiến nó đặc biệt có ý nghĩa
      Dù vậy, Ractor xứng đáng được chú ý hơn. Đây là một tính năng cực lớn
    • Tôi thật sự không hiểu vì sao lại không có một hàng đợi tác vụ chung cho cả Ruby và Python. Tôi biết rằng từ một thời điểm nào đó mọi người bắt đầu trao đổi thông tin qua microservice dựa trên HTTP, nhưng rốt cuộc một hàng đợi tác vụ đơn giản với định dạng lưu trữ mà cả hai ngôn ngữ cùng chia sẻ vẫn là cách tốt hơn để kết nối các hệ thống Ruby/Rails với stack machine learning
      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

    • Tôi không thấy có vấn đề gì với rbenv hay asdf. Tôi dùng cả hai ở môi trường local lẫn production
  • 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ạy getaddrinfo(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òn 100.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á

    • Tôi tự hỏi có phải vì mọi thao tác I/O trong thư viện chuẩn đều phải hỗ trợ async/fiber hay không
      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
    • Tôi nghĩ fiber có lẽ nhẹ hơn việc tạo một thread mới
  • 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ó

    • Về cơ bản, Ruby giống một Python ít phổ biến hơn nhưng thanh lịch hơn. Đây là một ngôn ngữ đa dụng vững chắc, đặc biệt phù hợp cho các tác vụ như shell script hay dọn dẹp dữ liệu
      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 cho rằng Ruby tốt hơn nhiều so với Python hay Node cho các tác vụ kiểu shell script và lập trình tương tác, khám phá dành cho công việc hệ thống. Chỉ cần dùng nó như “bash tốt hơn” hay “Perl tốt hơn” là đã đủ đáng giá
      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
    • Còn tùy bạn muốn đạt được điều gì. Phần thú vị nhất là Ruby ở nhiều mặt rất giống Python, nhưng đồng thời cũng khá khác
      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
    • Nếu muốn vừa học vừa lấy gợi ý để cải thiện mã, thì nên dùng Rubocop. Đây là một linter tuyệt vời đồng thời cũng là một người thầy
    • Tôi đã dùng Ruby, chính xác hơn là Ruby trong Rails, một chút vào giai đoạn 2011~2013, tức là hơn 10 năm trước. Khi đó vẫn còn dư âm của RoR, vốn xuất hiện từ 2005 và bùng nổ mạnh vào 2007~2009
      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à 8
    Tô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

    • Đây là kiểu tối ưu có thể bổ sung sau, và có chút tinh tế ở đây. Nếu nhớ không nhầm thì Go cũng từng tương tự trong vài năm, tôi còn nhớ việc đặt GO_MAX_PROCS trong init() hoặc main()
    • Có vẻ không đúng lắm khi đặt hard cap cho số CPU tối đa. Chẳng phải cứ phụ thuộc vào số lõi khả dụng là được sao
  • 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ó thể bạn sẽ quan tâm tới Im của Chris Salzberg. Nó đã dùng được ngay trong Ruby 3.2: https://github.com/shioyama/im
      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
    • Dù ngầm định hay tường minh thì tôi thấy global namespace vẫn ổn. Về lý thuyết thì hơi kỳ, nhưng trên thực tế nhờ quy ước và chuẩn mực xã hội nên hiếm khi thành vấn đề
      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ơ
    • Tôi nghĩ chuyện này thuộc về Rails chứ không phải Ruby. Tôi biết là trong đa số dự án thì khác biệt đó gần như không đáng kể, nhưng đây có thể là quyết định của đội ngũ Rails và không liên quan đến những gì đội ngũ Ruby đang làm
      Hoặc cũng có thể tôi đang nói hoàn toàn sai
    • Ruby 4.0 có lẽ phải trước năm 2030 mới khó mà thấy được
      https://youtu.be/4MM5b2F9zrM?si=UT3aUbD6p_uBZehS&t=2347