Ruby 3.0 có gì mới
Bài đăng này đã không được cập nhật trong 3 năm
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: 'john@example.com', 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