Ditulis oleh naruse tanggal 2020-12-25
Diterjemahkan oleh meisyal
Kami dengan senang hati mengumumkan rilis dari Ruby 3.0.0. Dari tahun 2015, kami bekerja keras untuk Ruby 3 yang mana tujuannya adalah kinerja, concurrency, dan Typing. Khususnya kinerja, Matz mengatakan “Ruby3 akan 3 kali lebih cepat dibanding Ruby2” yang juga dikenal dengan Ruby 3x3.
Dengan Optcarrot benchmark, yang mengukur
kinerja single thread berdasarkan beban kerja NES’s game emulation, kinerja
Ruby 3.0 mencapai 3x lebih cepat dibanding Ruby 2.0!
Ruby 3.0.0 mencapai tujuan tersebut dengan:
- Kinerja
- MJIT
- Concurrency
- Ractor
- Fiber Scheduler
- Typing (Analisis Statis)
- RBS
- TypeProf
Dengan perbaikan kinerja di atas, Ruby 3.0 mengenalkan sejumlah fitur baru yang digambarkan sebagai berikut.
Kinerja
Ketika saya menyatakan “Ruby3x3” pertama kali pada sebuah konferensi, banyak peserta termasuk anggota dari core team merasa “Matz is a boaster”. Kenyataannya, saya juga merasa begitu. Tetapi, kami berhasil. Saya merasa terhormat melihat core team benar-benar bisa menjadikan Ruby3.0 tiga kali lebih cepat dibanding Ruby2.0 (pada beberapa benchmark). – Matz
MJIT
Banyak perbaikan yang telah diimplementasikan pada MJIT. Lihat NEWS untuk detail.
Pada Ruby 3.0, JIT seharusnya memberikan perbaikan kinerja pada beban kerja terbatas, seperti permainan (Optcarrot), AI (Rubykon), atau aplikasi apapun yang mayoritas menghabiskan waktu saat memanggil beberapa method berkali-kali.
Meskipun Ruby 3.0 significantly decreased the size of JIT-ed code, ini masih belum siap untuk mengomptimalkan beban kerja seperti Rails, yang mana menghabiskan waktu pada banyak method. Sehingga, ini akan menderita dari i-cache misses yang diperburuk oleh JIT. Nantikan perbaikan lebih lanjut masalah ini pada Ruby 3.1.
Concurrency / Parallel
Ini zaman multi-core sekarang. Concurrency sangatlah penting. Dengan Ractor, bersama dengan Async Fiber, Ruby akan menjadi sebuah bahasa concurrent asli. — Matz
Ractor (eksperimental)
Ractor adalah sebuah Actor-model seperti concurrent abstraction yang didesain untuk menyediakan sebuah fitur eksekusi paralel tanpa mengkhawatirkan thread-safety.
Anda dapat membuat beberapa ractor dan menjalankannya secara paralel. Ractor memungkinkan untuk membuat program paralel yang thread-safe karena ractor tidak dapat membagi objek normal. Komunikasi antar ractor didukung oleh pertukaran pesan.
Untuk membatasi pembagian objek, Ractor mengenalkan beberapa batasan pada sintaks Ruby (tanpa banyak Ractor, maka tidak ada batasan).
Spesifikasi dan implementasi dari Ractor masih belum sempurna dan memungkinkan
adanya perubahan ke depan, sehingga fitur ini ditandai dengan eksperimental
dan menampilkan peringatan “experimental feature” saat Ractor.new
pertama kali.
Berikut adalah program kecil untuk mengukur waktu eksekusi dari fungsi populer tak (Tak (function) - Wikipedia), dengan mengeksekusinya 4 kali secara berurutan atau 4 kali secara paralel dengan Ractor.
def tarai(x, y, z) =
x <= y ? y : tarai(tarai(x-1, y, z),
tarai(y-1, z, x),
tarai(z-1, x, y))
require 'benchmark'
Benchmark.bm do |x|
# versi berurutan
x.report('seq'){ 4.times{ tarai(14, 7, 0) } }
# versi paralel
x.report('par'){
4.times.map do
Ractor.new { tarai(14, 7, 0) }
end.each(&:take)
}
end
Hasil benchmark:
user system total real
seq 64.560736 0.001101 64.561837 ( 64.562194)
par 66.422010 0.015999 66.438009 ( 16.685797)
Hasil diukur pada Ubuntu 20.04, Intel(R) Core(TM) i7-6700 (4 cores, 8 hardware threads). Ini menunjukkan versi paralel 3.87 kali lebih cepat dibanding versi berurutan.
Lihat doc/ractor.md untuk lebih detail.
Fiber Scheduler
Fiber#scheduler
diperkenalkan untuk menghalangi operasi blocking. Ini
memperbolehkan light-weight concurrency tanpa pengubahan kode yang sudah ada.
Tonton “Don’t Wait For Me, Scalable Concurrency for Ruby 3”
sebagai gambaran bagaimana fitur ini bekerja.
Saat ini, class/method yang didukung:
Mutex#lock
,Mutex#unlock
,Mutex#sleep
ConditionVariable#wait
Queue#pop
,SizedQueue#push
Thread#join
Kernel#sleep
Process.wait
IO#wait
,IO#read
,IO#write
, dan method yang berkaitan (seperti#wait_readable
,#gets
,#puts
dan lainnya).IO#select
tidak didukung.
Ini adalah contoh program yang akan melakukan beberapa HTTP request secara bersamaan:
require 'async'
require 'net/http'
require 'uri'
Async do
["ruby", "rails", "async"].each do |topic|
Async do
Net::HTTP.get(URI "https://www.google.com/search?q=#{topic}")
end
end
end
Ini menggunakan async yang mana menyediakan
event loop. Event loop ini menggunakan Fiber#scheduler
hook untuk
membuat Net::HTTP
non-blocking. Gem lainnya dapat menggunakan interface
ini untuk menyediakan eksekusi non-blocking pada Ruby dan gem tersebut
cocok dengan implementasi Ruby lainnya (misalnya, JRuby, TruffleRuby) yang dapat
mendukung non-blocking hook yang sama.
Analisis Statis
2010-an adalah zaman dari statically typed programming language. Ruby melihat masa depan dengan static type checking, tanpa type declaration, menggunakan interpretasi abstrak. RBS & TypeProf adalah langkah pertama menuju masa depan. Lebih banyak langkah yang akan datang. — Matz
RBS
RBS adalah sebuah bahasa untuk mendeskripsikan tipe dari program Ruby.
Type checker termasuk TypeProf dan tool lainnya yang mendukung RBS akan memahami program Ruby jauh lebih baik dengan definisi RBS.
Anda dapat menuliskan definisi class dan module: method didefinisikan di dalam class, instance variables dan tipenya, serta hubungan inheritance/mix-in.
RBS memiliki tujuan untuk mendukung pola yang biasanya kita lihat dalam program Ruby dan memperbolehkan penulisan advanced types yang berisi union type, method overloading, dan generic. RBS juga mendukung duck typing dengan interface types.
Ruby 3.0 dirilis dengan gem rbs
, yang memperbolehkan untuk mem-parse dan
memproses definisi tipe yang ditulis di dalam RBS. Berikut ini adalah sebuah
contoh kecil dari RBS dengan class, module, dan constant definition.
module ChatApp
VERSION: String
class Channel
attr_reader name: String
attr_reader messages: Array[Message]
attr_reader users: Array[User | Bot] # `|` means union types, `User` or `Bot`.
def initialize: (String) -> void
def post: (String, from: User | Bot) -> Message # Method overloading is supported.
| (File, from: User | Bot) -> Message
end
end
Lihat README dari gem rbs untuk lebih detail.
TypeProf
TypeProf adalah sebuah type analysis tool yang di-bundle di dalam Ruby.
Saat ini, TypeProf berperan semacam sebuah type inference.
TypeProf membaca kode Ruby (non-type-annotated), menganalisis apa method yang didefinisikan dan bagaimana itu digunakan, dan menghasilkan sebuah prototipe dari type signature dalam format RBS.
Berikut adalah sebuah demonstrasi sederhana dari TypeProf.
Contoh masukan:
# test.rb
class User
def initialize(name:, age:)
@name, @age = name, age
end
attr_reader :name, :age
end
User.new(name: "John", age: 20)
Contoh keluaran:
$ typeprof test.rb
# Classes
class User
attr_reader name : String
attr_reader age : Integer
def initialize : (name: String, age: Integer) -> [String, Integer]
end
Anda dapat menjalankan TypeProf dengan menyimpan masukan sebagai “test.rb” dan memanggilnya dengan perintah “typeprof test.rb”.
Anda juga dapat mencoba TypeProf daring. (Ini menjalankan TypeProf di server, maaf jika hasilnya tidak keluar)
Lihat dokumentasi dan demonstrasi untuk detail.
TypeProf masih eksperimental dan belum sempurna; hanya sebagian dari bahasa Ruby didukung dan pendeteksian type error terbatas. Tetapi, ini masih bisa berkembang dengan memperbaiki cakupan dari fitur bahasa, performa analisis, dan kegunaan. Masukan apapun sangat diterima.
Fitur Baru Lainnya
-
One-line pattern matching didesain ulang. (eksperimental)
-
=>
ditambahkan. Ini bisa digunakan seperti rightward assignment.0 => a p a #=> 0 {b: 0, c: 1} => {b:} p b #=> 0
-
in
diubah dengan mengembalikantrue
ataufalse
.# version 3.0 0 in 1 #=> false # version 2.7 0 in 1 #=> raise NoMatchingPatternError
-
-
Find pattern ditambahkan. (eksperimental)
case ["a", 1, "b", "c", 2, "d", "e", "f", 3] in [*pre, String => x, String => y, *post] p pre #=> ["a", 1] p x #=> "b" p y #=> "c" p post #=> [2, "d", "e", "f", 3] end
-
Definisi endless method ditambahkan.
def square(x) = x * x
-
Hash#except
sekarang built-in.h = { a: 1, b: 2, c: 3 } p h.except(:a) #=> {:b=>2, :c=>3}
-
Memory view ditambahkan sebagai sebuah fitur eksperimental
- Ini adalah sebuah kumpulan C-API baru yang menukar sebuah area raw memory, seperti sebuah numeric array dan sebuah bitmap image, antara pustaka extension. Pustaka extension dapat juga membagikan metadata dari area memory yang terdiri dari bentuk, format elemen, dan sebagainya. Menggunakan semacam metadata seperti ini, pustaka extension bahkan dapat membagikan sebuah multidimensional array dengan tepat. Fitur ini didesain dengan merujuk pada buffer protocol dari Python.
Perbaikan performa
- Menempelkan kode yang panjang pada IRB 53 kali lebih cepat dibandingkan yang di-bundle dengan Ruby 2.7.0. Sebagai contoh, waktu yang dibutuhkan untuk menempelkan kode ini berubah dari 11.7 detik menjadi 0.22 detik.
-
Perintah
measure
telah ditambakan ke IRB. Ini memperbolehkan perhitungan waktu eksekusi secara sederhana.irb(main):001:0> 3 => 3 irb(main):002:0> measure TIME is added. => nil irb(main):003:0> 3 processing time: 0.000058s => 3 irb(main):004:0> measure :off => nil irb(main):005:0> 3 => 3
Perubahan penting lainnya sejak 2.7
- Keyword argument dipisahkan dari argument lainnya.
- Pada dasarnya, kode yang mencetak sebuah peringatan pada Ruby 2.7 tidak akan bekerja. Lihat dokumen untuk detail.
-
Omong-omong, argument forwarding sekarang mendukung leading argument.
def method_missing(meth, ...) send(:"do_#{ meth }", ...) end
- Pattern matching (
case
/in
) tidak lagi eksperimental.- Lihat dokumentasi pattern matching untuk detail.
- Fitur
$SAFE
telah dihilangkan; sekarang adalah sebuah variabel global. - Urutan dari backtrace telah dibalik pada Ruby 2.5, tetapi itu dibatalkan. Sekarang urutan berperilaku seperti Ruby 2.4; pesan error dan nomor baris di mana exception terjadi dicetak terlebih dahulu dan pemanggilnya baru dicetak kemudian.
- Beberapa pustaka standar yang diperbarui.
- Berikut adalah pustaka yang tidak lagi masuk sebagai bundled gem.
- RubyGems 3.2.3
- Bundler 2.2.3
- IRB 1.3.0
- Reline 0.2.0
- Psych 3.3.0
- JSON 2.5.1
- BigDecimal 3.0.0
- CSV 3.1.9
- Date 3.1.0
- Digest 3.0.0
- Fiddle 1.0.6
- StringIO 3.0.0
- StringScanner 3.0.0
- lainnya.
- Pustakan berikut tidak lagi bundle gem atau pustaka standar.
Pasang gem berikut jika ingin menggunakan fiturnya.
- sdbm
- webrick
- net-telnet
- xmlrpc
- Berikut adalah default gem yang sekarang menjadi bundled gem.
- rexml
- rss
- Berikut adalah berkas stdlib yang sekarang menjadi default gem dan telah dipublikasikan ke rubygems.org
- English
- abbrev
- base64
- drb
- debug
- erb
- find
- net-ftp
- net-http
- net-imap
- net-protocol
- open-uri
- optparse
- pp
- prettyprint
- resolv-replace
- resolv
- rinda
- set
- securerandom
- shellwords
- tempfile
- tmpdir
- time
- tsort
- un
- weakref
- digest
- io-nonblock
- io-wait
- nkf
- pathname
- syslog
- win32ole
Lihat NEWS atau commit logs untuk lebih detail.
Dengan perubahan tersebut, 4028 berkas berubah, 200058 sisipan(+), 154063 terhapus(-) sejak Ruby 2.7.0!
Selamat Natal, selamat berlibur, dan nikmati memprogram dengan Ruby 3.0!
Unduh
-
https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.tar.gz
SIZE: 19539509 SHA1: 233873708c1ce9fdc295e0ef1c25e64f9b98b062 SHA256: a13ed141a1c18eb967aac1e33f4d6ad5f21be1ac543c344e0d6feeee54af8e28 SHA512: e62f4f63dc12cff424e8a09adc06477e1fa1ee2a9b2b6e28ca22fd52a211e8b8891c0045d47935014a83f2df2d6fc7c8a4fd87f01e63c585afc5ef753e1dd1c1
-
https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.tar.xz
SIZE: 14374176 SHA1: c142899d70a1326c5a71311b17168f98c15e5d89 SHA256: 68bfaeef027b6ccd0032504a68ae69721a70e97d921ff328c0c8836c798f6cb1 SHA512: 2a23c2894e62e24bb20cec6b2a016b66d7df05083668726b6f70af8338211cfec417aa3624290d1f5ccd130f65ee7b52b5db7d428abc4a9460459c9a5dd1a450
-
https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.zip
SIZE: 23862057 SHA1: 2a9629102d71c7fe7f31a8c91f64e570a40d093c SHA256: a5e4fa7dc5434a7259e9a29527eeea2c99eeb5e82708f66bb07731233bc860f4 SHA512: e5bf742309d79f05ec1bd1861106f4b103e4819ca2b92a826423ff451465b49573a917cb893d43a98852435966323e2820a4b9f9377f36cf771b8c658f80fa5b
Apa itu Ruby
Ruby pertama kali dikembangkan oleh Matz (Yukihiro Matsumoto) pada 1993 dan sekarang dikembangkan sebagai Open Source. Ruby berjalan di berbagai jenis platform dan digunakan di seluruh dunia khususnya pengembangan web.