Posted by naruse on 25 Dec 2020
We are pleased to announce the release of Ruby 3.0.0. From 2015 we developed hard toward Ruby 3, whose goal is performance, concurrency, and Typing. Especially about performance, Matz stated “Ruby3 will be 3 times faster than Ruby2” a.k.a.Ruby 3x3.

WithOptcarrot benchmark, which measures single thread performance based on NES’s game emulation workload, it achieved 3x faster performance than Ruby 2.0!
Ruby 3.0.0 covers those goals by
With the above performance improvement, Ruby 3.0 introduces several new features described below.
When I first declared “Ruby3x3” in the conference keynote, many including members of the core team felt “Matz is a boaster”. In fact, I felt so too. But we did. I am honored to see the core team actually accomplished to make Ruby3.0 three times faster than Ruby2.0 (in some benchmarks). – Matz
Many improvements were implemented in MJIT. See NEWS for details.
As of Ruby 3.0, JIT is supposed to give performance improvements in limited workloads, such as games (Optcarrot), AI (Rubykon), or whatever application that spends the majority of time in calling a few methods many times.
Although Ruby 3.0significantly decreased the size of JIT-ed code, it is still not ready for optimizing workloads like Rails, which often spend time on so many methods and therefore suffer from i-cache misses exacerbated by JIT. Stay tuned for Ruby 3.1 for further improvements on this issue.
It’s multi-core age today. Concurrency is very important. With Ractor, along with Async Fiber, Ruby will be a real concurrent language. — Matz
Ractor is an Actor-model like concurrent abstraction designed to provide a parallel execution feature without thread-safety concerns.
You can make multiple ractors and you can run them in parallel. Ractor enables you to make thread-safe parallel programs because ractors can not share normal objects. Communication between ractors is supported by exchanging messages.
To limit the sharing of objects, Ractor introduces several restrictions to Ruby’s syntax (without multiple Ractors, there is no restriction).
The specification and implementation are not matured and may be changed in the future, so this feature is marked as experimental and shows the “experimental feature” warning when the firstRactor.new occurs.
The following small program measures the execution time of the famous benchmark tak function (Tak (function) - Wikipedia), by executing it 4 times sequentially or 4 times in parallel with ractors.
deftarai(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.bmdo|x|# sequential versionx.report('seq'){4.times{tarai(14,7,0)}}# parallel versionx.report('par'){4.times.mapdoRactor.new{tarai(14,7,0)}end.each(&:take)}endBenchmark result: user system total realseq 64.560736 0.001101 64.561837 ( 64.562194)par 66.422010 0.015999 66.438009 ( 16.685797)The result was measured on Ubuntu 20.04, Intel(R) Core(TM) i7-6700 (4 cores, 8 hardware threads). It shows that the parallel version is 3.87 times faster than the sequential version.
Seedoc/ractor.md for more details.
Fiber#scheduler is introduced for intercepting blocking operations. This allows for light-weight concurrency without changing existing code. Watch“Don’t Wait For Me, Scalable Concurrency for Ruby 3” for an overview of how it works.
Currently supported classes/methods:
Mutex#lock,Mutex#unlock,Mutex#sleepConditionVariable#waitQueue#pop,SizedQueue#pushThread#joinKernel#sleepProcess.waitIO#wait,IO#read,IO#write, and related methods (e.g.#wait_readable,#gets,#puts, and so on).IO#select isnot supported.This example program will perform several HTTP requests concurrently:
require'async'require'net/http'require'uri'Asyncdo["ruby","rails","async"].eachdo|topic|AsyncdoNet::HTTP.get(URI"https://www.google.com/search?q=#{topic}")endendendIt usesasync which provides the event loop. This event loop uses theFiber#scheduler hooks to makeNet::HTTP non-blocking. Other gems can use this interface to provide non-blocking execution for Ruby, and those gems can be compatible with other implementations of Ruby (e.g. JRuby, TruffleRuby) which can support the same non-blocking hooks.
2010s were an age of statically typed programming languages. Ruby seeks the future with static type checking, without type declaration, using abstract interpretation. RBS & TypeProf are the first step to the future. More steps to come. — Matz
RBS is a language to describe the types of Ruby programs.
Type checkers including TypeProf and other tools supporting RBS will understand Ruby programs much better with RBS definitions.
You can write down the definition of classes and modules: methods defined in the class, instance variables and their types, and inheritance/mix-in relations.
The goal of RBS is to support commonly seen patterns in Ruby programs and it allows writing advanced types including union types, method overloading, and generics. It also supports duck typing withinterface types.
Ruby 3.0 ships with therbs gem, which allows parsing and processing type definitions written in RBS.The following is a small example of RBS with class, module, and constant definitions.
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 endendSeeREADME of rbs gem for more detail.
TypeProf is a type analysis tool bundled in the Ruby package.
Currently, TypeProf serves as a kind of type inference.
It reads plain (non-type-annotated) Ruby code, analyzes what methods are defined and how they are used, and generates a prototype of type signature in RBS format.
Here is a simple demo of TypeProf.
An example input:
# test.rbclassUserdefinitialize(name:,age:)@name,@age=name,ageendattr_reader:name,:ageendUser.new(name:"John",age:20)An example output:
$ typeprof test.rb# Classesclass User attr_reader name : String attr_reader age : Integer def initialize : (name: String, age: Integer) -> [String, Integer]endYou can run TypeProf by saving the input as “test.rb” and invoking the command “typeprof test.rb”.
You can alsotry TypeProf online. (It runs TypeProf on the server side, so sorry if it is out!)
See theTypeProf documentation anddemos for details.
TypeProf is experimental and not so mature yet; only a subset of the Ruby language is supported, and the detection of type errors is limited. But it is still growing rapidly to improve the coverage of language features, the analysis performance, and usability. Any feedback is very welcome.
One-line pattern matching is redesigned. (experimental)
=> is added. It can be used like a rightward assignment.
0=>apa#=> 0{b:0,c:1}=>{b:}pb#=> 0in is changed to returntrue orfalse.
# version 3.00in1#=> false# version 2.70in1#=> raise NoMatchingPatternErrorFind pattern is added. (experimental)
case["a",1,"b","c",2,"d","e","f",3]in[*pre,String=>x,String=>y,*post]ppre#=> ["a", 1]px#=> "b"py#=> "c"ppost#=> [2, "d", "e", "f", 3]endEndless method definition is added.
defsquare(x)=x*xHash#except is now built-in.
h={a:1,b:2,c:3}ph.except(:a)#=> {:b=>2, :c=>3}Memory view is added as an experimental feature
Themeasure command has been added to IRB. It allows simple execution time measurement.
irb(main):001:0> 3=> 3irb(main):002:0> measureTIME is added.=> nilirb(main):003:0> 3processing time: 0.000058s=> 3irb(main):004:0> measure :off=> nilirb(main):005:0> 3=> 3By the way, arguments forwarding now supports leading arguments.
defmethod_missing(meth,...)send(:"do_#{meth}",...)endcase/in) is no longer experimental.$SAFE feature was completely removed; now it is a normal global variable.SeeNEWSorcommit logsfor more details.
With those changes,4028 files changed, 200058 insertions(+), 154063 deletions(-)since Ruby 2.7.0!
Ruby3.0 is a milestone. The language is evolved, keeping compatibility. But it’s not the end. Ruby will keep progressing, and become even greater. Stay tuned! — Matz
Merry Christmas, Happy Holidays, and enjoy programming with Ruby 3.0!
https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.tar.gz
SIZE: 19539509SHA1: 233873708c1ce9fdc295e0ef1c25e64f9b98b062SHA256: a13ed141a1c18eb967aac1e33f4d6ad5f21be1ac543c344e0d6feeee54af8e28SHA512: e62f4f63dc12cff424e8a09adc06477e1fa1ee2a9b2b6e28ca22fd52a211e8b8891c0045d47935014a83f2df2d6fc7c8a4fd87f01e63c585afc5ef753e1dd1c1https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.tar.xz
SIZE: 14374176SHA1: c142899d70a1326c5a71311b17168f98c15e5d89SHA256: 68bfaeef027b6ccd0032504a68ae69721a70e97d921ff328c0c8836c798f6cb1SHA512: 2a23c2894e62e24bb20cec6b2a016b66d7df05083668726b6f70af8338211cfec417aa3624290d1f5ccd130f65ee7b52b5db7d428abc4a9460459c9a5dd1a450https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.zip
SIZE: 23862057SHA1: 2a9629102d71c7fe7f31a8c91f64e570a40d093cSHA256: a5e4fa7dc5434a7259e9a29527eeea2c99eeb5e82708f66bb07731233bc860f4SHA512: e5bf742309d79f05ec1bd1861106f4b103e4819ca2b92a826423ff451465b49573a917cb893d43a98852435966323e2820a4b9f9377f36cf771b8c658f80fa5bRuby was first developed by Matz (Yukihiro Matsumoto) in 1993and is now developed as Open Source. It runs on multiple platformsand is used all over the world especially for web development.