Ruby 3.0 có gì mới

Ruby 3.0.0 đã được ra mới được ra mắt vào tháng 12/2020, mục tiêu của bản 3.0.0 là vê hiệu suất, xử lý đồng thời, và cú pháp. Đặc biệt về hiệu suất, Ruby3 sẽ nhanh gấp 3 lần Ruby2.

Performance

MJIT

Trong phiên bản Ruby 3.0, JIT cung cấp các cải tiến về hiệu suất trong khối lượng cộng việc bị hạn chế, chẳng hạn như trò chơi (Optcarrot), AI (Rubykon) hoặc bất kỳ chuong trình nào dành nhiều thời gian để gọi một vài phương thức nhiều lần.

Mặc dù Ruby 3.0 giảm đáng kể kích thước của mã JIT-ed, nhưng nó vẫn chưa sẵn sàng để tối ưu các khối lượng công việc như Rails, ddieeuff này gây lãng phí thời gian cho quá nhiều phương thức và do đó gặp phải vấn đề i-cache do JIT làm trầm trọng thêm.

Nếu bạn quan tâm đến vấn đề này, có thể theo dõi bản Ruby 3.1.

Concurrency / Parallel

Ractor

Ractor là một Actor-model được thiết kế để cung cấp tính năng cho việc thực thi song song mà không cần lo về thread-safe.

Bạn có thể tạo nhiều Ractor và bạn có thể chạy chúng song song. Ractor cho phép tạo các chương trình song song thread-safe. Giao tiếp giữa các ractor được hỗ trợ bằng cách trao đổi tin nhắn.

Ractor hiện tại vẫn đang thử nghiệm và có thể thay sẽ có thay đổi trong tương lai

Ví dụ:

def tarai(x, y, z)
   x <= y ? y : tarai(tarai(x-1, y, z),
                      tarai(y-1, z, x),
                      tarai(z-1, x, y))
end

require 'benchmark'
Benchmark.bm do |x|
   # sequential version
   x.report('seq'){ 4.times{ tarai(14, 7, 0) } }

   # parallel version
   x.report('par'){
      4.times.map do
         Ractor.new { tarai(14, 7, 0) }
      end.each(&:take)
   }
end

Ví dụ trên thực hiện hàm tak (Tak (function) - Wikipedia), bằng cách thực hiện tuần tự nó 4 lần và thực hiện song song sử dụng Ractor.

Benchmark result:

user system total real
seq 96.110529 0.023944 96.134473 96.210604
par 140.141838 0.377855 140.519693 45.331722

Kết quả được đo trên Ubuntu 19.10, Intel® Core™ i5-7200U ( 4 cores, 8 luồng ). Nó cho thấy khi chay song song nhanh gấp hơn 2 lần so với chạy tuần tự.

Fiber Scheduler

Fiber#scheduler được giới thiệu để ngăn việc chặn các hoạt động chẳng hạn như I/O. Nó cho phép cho phép việc sử dụng đồng thời nhưng nhẹ hơn mà không cần thay đổi mã hiện tại

Ví dụ:

require 'async'
require 'net/http'
require 'uri'

start = Time.now

Async do
  ["ruby", "rails", "async"].each do |topic|
    Async do
      t = Time.now
      Net::HTTP.get(URI "https://www.google.com/search?q=#{topic}")
      p '%s: finished in %.3f' % [topic, Time.now - t]
    end
  end
end

p 'Total: finished in %.3f' %(Time.now - start)

Ví dụ trên sử dụng gem async để cung cấp vòng lặp. Vòng lặp này sử dụng các Fiber#scheduler để thực hiện Net::HTTP non-blocking.

Kết quả:

"ruby: finished in 0.662"
"rails: finished in 0.866"
"async: finished in 1.464"
"Total: finished in 1.465"

Static Analysis

RBS

RBS là một ngôn nhữ để mo tẩ cấu trúc một chương trình Ruby. Nó cung cấp cái nhìn tổng quan về chương trình và các class, method,... được định nghĩa. Sử dụng RBS, có thể định nghĩa các class, methods, modules, biến, kiểu biến và kế thừa

Ví dụ:

class User
  def initialize: (name: String, email: String, age: Integer | String) -> ([String, String, Integer | String])
  attr_reader name: String
  attr_reader email: String
  attr_reader age: Integer | String
end

Typeprof

Việc giới thiệu một dịnh nghĩa kiểu mới là một thách thức vì hiện giờ có rất nhiều mã Ruby và chúng ta thực sự cần một công cụ để chuyển đổi. Typeprof là một công cụ phân tích kiểu mã ruby thuần túy và tạo một bản mã viết theo định dạng RBS.

Ví dụ:

# user.rb
class User

  def initialize(name:, email:, age:)
    @name, @email, @age = name, email, age
  end

  attr_reader :name, :email, :age
end

User.new(name: "John Doe", email: '[email protected]', age: 23)

Đầu ra

$ typeprof user.rb

# Classes
class User

  attr_reader name : String
  attr_reader email : String
  attr_reader age : Integer

  def initialize : (name: String,
                    email: String,
                    age: Integer) -> [String, String, Integer]

end

Trong vị dụ trên, typeprof sẽ dựa vào các giá trị khị khởi tạo class User để định nghĩa kiểu biến cho từng biến.

Một số tính năng khác

Định nghĩa phương thức không cần end

def square(x) = x * x
p square(2)  # => 4

Thêm method except cho Hash

h = { a: 1, b: 2, c: 3 }
p h.except(:a) # => {:b=>2, :c=>3}

Tham khảo https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/


All Rights Reserved