Skip to content

Commit 89d86a0

Browse files
committed
Import original article
1 parent 648ba8c commit 89d86a0

File tree

1 file changed

+391
-0
lines changed

1 file changed

+391
-0
lines changed
Lines changed: 391 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,391 @@
1+
---
2+
layout: news_post
3+
title: "Ruby 3.0.0 Released"
4+
author: "naruse"
5+
translator:
6+
date: 2020-12-25 00:00:00 +0000
7+
lang: en
8+
---
9+
10+
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](https://blog.heroku.com/ruby-3-by-3).
11+
12+
{% assign release = site.data.releases | where: "version", "3.0.0" | first %}
13+
14+
<img src='https://cache.ruby-lang.org/pub/media/ruby3x3.png' alt='Optcarrot 3000 frames' width='100%' />
15+
16+
With [Optcarrot benchmark](https://github.com/mame/optcarrot), which measures single thread performance based on NES's game emulation workload, it achieved 3x faster performance than Ruby 2.0! <details>These were measured at the environment noted in [benchmark-driver.github.io/hardware.html](https://benchmark-driver.github.io/hardware.html). [Commit 8c510e4095](https://github.com/ruby/ruby/commit/8c510e4095) was used as Ruby 3.0. It may not be 3x faster depending on your environment or benchmark.</details>
17+
18+
Ruby 3.0.0 covers those goals by
19+
* Performance
20+
* MJIT
21+
* Concurrency
22+
* Ractor
23+
* Fiber Scheduler
24+
* Typing (Static Analysis)
25+
* RBS
26+
* TypeProf
27+
28+
With the above performance improvement, Ruby 3.0 introduces several new features described below.
29+
30+
## Performance
31+
32+
> 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
33+
34+
### MJIT
35+
36+
Many improvements were implemented in MJIT. See NEWS for details.
37+
38+
As of Ruby 3.0, JIT is supposed to give performance improvements in limited workloads, such as games ([Optcarrot](https://benchmark-driver.github.io/benchmarks/optcarrot/commits.html#chart-1)), AI ([Rubykon](https://benchmark-driver.github.io/benchmarks/rubykon/commits.html)), or whatever application that spends the majority of time in calling a few methods many times.
39+
40+
Although Ruby 3.0 [significantly decreased the size of JIT-ed code](https://twitter.com/k0kubun/status/1256142302608650244), 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.
41+
42+
## Concurrency / Parallel
43+
44+
> It's multi-core age today. Concurrency is very important. With Ractor, along with Async Fiber, Ruby will be a real concurrent language. --- Matz
45+
46+
### Ractor (experimental)
47+
48+
Ractor is an Actor-model like concurrent abstraction designed to provide a parallel execution feature without thread-safety concerns.
49+
50+
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.
51+
52+
To limit the sharing of objects, Ractor introduces several restrictions to Ruby's syntax (without multiple Ractors, there is no restriction).
53+
54+
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 first `Ractor.new` occurs.
55+
56+
The following small program measures the execution time of the famous benchmark tak function ([Tak (function) - Wikipedia](https://en.wikipedia.org/wiki/Tak_(function))), by executing it 4 times sequentially or 4 times in parallel with ractors.
57+
58+
``` ruby
59+
def tarai(x, y, z) =
60+
x <= y ? y : tarai(tarai(x-1, y, z),
61+
tarai(y-1, z, x),
62+
tarai(z-1, x, y))
63+
require 'benchmark'
64+
Benchmark.bm do |x|
65+
# sequential version
66+
x.report('seq'){ 4.times{ tarai(14, 7, 0) } }
67+
68+
# parallel version
69+
x.report('par'){
70+
4.times.map do
71+
Ractor.new { tarai(14, 7, 0) }
72+
end.each(&:take)
73+
}
74+
end
75+
```
76+
77+
```
78+
Benchmark result:
79+
user system total real
80+
seq 64.560736 0.001101 64.561837 ( 64.562194)
81+
par 66.422010 0.015999 66.438009 ( 16.685797)
82+
```
83+
84+
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.
85+
86+
See [doc/ractor.md](https://docs.ruby-lang.org/en/3.0.0/doc/ractor_md.html) for more details.
87+
88+
### Fiber Scheduler
89+
90+
`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"](https://www.youtube.com/watch?v=Y29SSOS4UOc) for an overview of how it works.
91+
92+
Currently supported classes/methods:
93+
94+
- `Mutex#lock`, `Mutex#unlock`, `Mutex#sleep`
95+
- `ConditionVariable#wait`
96+
- `Queue#pop`, `SizedQueue#push`
97+
- `Thread#join`
98+
- `Kernel#sleep`
99+
- `Process.wait`
100+
- `IO#wait`, `IO#read`, `IO#write`, and related methods (e.g. `#wait_readable`, `#gets`, `#puts`, and so on).
101+
- `IO#select` is *not supported*.
102+
103+
This example program will perform several HTTP requests concurrently:
104+
105+
``` ruby
106+
require 'async'
107+
require 'net/http'
108+
require 'uri'
109+
110+
Async do
111+
["ruby", "rails", "async"].each do |topic|
112+
Async do
113+
Net::HTTP.get(URI "https://www.google.com/search?q=#{topic}")
114+
end
115+
end
116+
end
117+
```
118+
119+
It uses [async](https://github.com/socketry/async) which provides the event loop. This event loop uses the `Fiber#scheduler` hooks to make `Net::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.
120+
121+
## Static Analysis
122+
123+
> 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
124+
125+
### RBS
126+
127+
RBS is a language to describe the types of Ruby programs.
128+
129+
Type checkers including TypeProf and other tools supporting RBS will understand Ruby programs much better with RBS definitions.
130+
131+
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.
132+
133+
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 with _interface types_.
134+
135+
Ruby 3.0 ships with the `rbs` gem, which allows parsing and processing type definitions written in RBS.
136+
The following is a small example of RBS with class, module, and constant definitions.
137+
138+
``` rbs
139+
module ChatApp
140+
VERSION: String
141+
class Channel
142+
attr_reader name: String
143+
attr_reader messages: Array[Message]
144+
attr_reader users: Array[User | Bot] # `|` means union types, `User` or `Bot`.
145+
def initialize: (String) -> void
146+
def post: (String, from: User | Bot) -> Message # Method overloading is supported.
147+
| (File, from: User | Bot) -> Message
148+
end
149+
end
150+
```
151+
152+
See [README of rbs gem](https://github.com/ruby/rbs) for more detail.
153+
154+
### TypeProf
155+
156+
TypeProf is a type analysis tool bundled in the Ruby package.
157+
158+
Currently, TypeProf serves as a kind of type inference.
159+
160+
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.
161+
162+
Here is a simple demo of TypeProf.
163+
164+
An example input:
165+
166+
``` ruby
167+
# test.rb
168+
class User
169+
def initialize(name:, age:)
170+
@name, @age = name, age
171+
end
172+
attr_reader :name, :age
173+
end
174+
User.new(name: "John", age: 20)
175+
```
176+
177+
An example output:
178+
179+
```
180+
$ typeprof test.rb
181+
# Classes
182+
class User
183+
attr_reader name : String
184+
attr_reader age : Integer
185+
def initialize : (name: String, age: Integer) -> [String, Integer]
186+
end
187+
```
188+
189+
You can run TypeProf by saving the input as "test.rb" and invoking the command "typeprof test.rb".
190+
191+
You can also [try TypeProf online](https://mame.github.io/typeprof-playground/#rb=%23+test.rb%0Aclass+User%0A++def+initialize%28name%3A%2C+age%3A%29%0A++++%40name%2C+%40age+%3D+name%2C+age%0A++end%0A++%0A++attr_reader+%3Aname%2C+%3Aage%0Aend%0A%0AUser.new%28name%3A+%22John%22%2C+age%3A+20%29&rbs=). (It runs TypeProf on the server side, so sorry if it is out!)
192+
193+
See the [TypeProf documentation](https://github.com/ruby/typeprof/blob/master/doc/doc.md) and [demos](https://github.com/ruby/typeprof/blob/master/doc/demo.md) for details.
194+
195+
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.
196+
197+
## Other Notable New Features
198+
199+
* One-line pattern matching is redesigned. (experimental)
200+
201+
* `=>` is added. It can be used like a rightward assignment.
202+
203+
```ruby
204+
0 => a
205+
p a #=> 0
206+
207+
{b: 0, c: 1} => {b:}
208+
p b #=> 0
209+
```
210+
211+
* `in` is changed to return `true` or `false`.
212+
213+
```ruby
214+
# version 3.0
215+
0 in 1 #=> false
216+
217+
# version 2.7
218+
0 in 1 #=> raise NoMatchingPatternError
219+
```
220+
221+
* Find pattern is added. (experimental)
222+
223+
``` ruby
224+
case ["a", 1, "b", "c", 2, "d", "e", "f", 3]
225+
in [*pre, String => x, String => y, *post]
226+
p pre #=> ["a", 1]
227+
p x #=> "b"
228+
p y #=> "c"
229+
p post #=> [2, "d", "e", "f", 3]
230+
end
231+
```
232+
233+
* Endless method definition is added.
234+
235+
``` ruby
236+
def square(x) = x * x
237+
```
238+
239+
* `Hash#except` is now built-in.
240+
241+
``` ruby
242+
h = { a: 1, b: 2, c: 3 }
243+
p h.except(:a) #=> {:b=>2, :c=>3}
244+
```
245+
246+
* Memory view is added as an experimental feature
247+
248+
* This is a new C-API set to exchange a raw memory area, such as a numeric array or a bitmap image, between extension libraries. The extension libraries can share also the metadata of the memory area that consists of the shape, the element format, and so on. Using these kinds of metadata, the extension libraries can share even a multidimensional array appropriately. This feature is designed by referring to Python's buffer protocol.
249+
250+
## Performance improvements
251+
252+
* Pasting long code to IRB is 53 times faster than in the version bundled with Ruby 2.7.0. For example, the time required to paste [this sample code](https://gist.github.com/aycabta/30ab96334275bced5796f118c9220b0b) goes from 11.7 seconds to 0.22 seconds.
253+
254+
255+
<video autoplay="autoplay" controls="controls" muted="muted" width="764" height="510" poster="https://cache.ruby-lang.org/pub/media/ruby-3.0-irb-highspeed.png">
256+
<source src="https://cache.ruby-lang.org/pub/media/ruby-3.0-irb-highspeed.mp4" type="video/mp4">
257+
</video>
258+
259+
260+
* The `measure` command has been added to IRB. It allows simple execution time measurement.
261+
262+
```
263+
irb(main):001:0> 3
264+
=> 3
265+
irb(main):002:0> measure
266+
TIME is added.
267+
=> nil
268+
irb(main):003:0> 3
269+
processing time: 0.000058s
270+
=> 3
271+
irb(main):004:0> measure :off
272+
=> nil
273+
irb(main):005:0> 3
274+
=> 3
275+
```
276+
277+
## Other notable changes since 2.7
278+
279+
* Keyword arguments are separated from other arguments.
280+
* In principle, code that prints a warning on Ruby 2.7 won't work. See [this document](https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/) for details.
281+
* By the way, arguments forwarding now supports leading arguments.
282+
283+
``` ruby
284+
def method_missing(meth, ...)
285+
send(:"do_#{ meth }", ...)
286+
end
287+
```
288+
289+
* Pattern matching (`case`/`in`) is no longer experimental.
290+
* See the [pattern matching documentation](https://docs.ruby-lang.org/en/3.0.0/doc/syntax/pattern_matching_rdoc.html) for details.
291+
* The `$SAFE` feature was completely removed; now it is a normal global variable.
292+
* The order of backtraces had been reversed with Ruby 2.5; this change has been reverted. Now backtraces behave like in Ruby 2.4: an error message and the line number where the exception occurs are printed first, and its callers are printed later.
293+
* Some standard libraries are updated.
294+
* RubyGems 3.2.3
295+
* Bundler 2.2.3
296+
* IRB 1.3.0
297+
* Reline 0.2.0
298+
* Psych 3.3.0
299+
* JSON 2.5.1
300+
* BigDecimal 3.0.0
301+
* CSV 3.1.9
302+
* Date 3.1.0
303+
* Digest 3.0.0
304+
* Fiddle 1.0.6
305+
* StringIO 3.0.0
306+
* StringScanner 3.0.0
307+
* etc.
308+
* The following libraries are no longer bundled gems or standard libraries.
309+
Install the corresponding gems to use these features.
310+
* sdbm
311+
* webrick
312+
* net-telnet
313+
* xmlrpc
314+
* The following default gems are now bundled gems.
315+
* rexml
316+
* rss
317+
* The following stdlib files are now default gems and are published on rubygems.org.
318+
* English
319+
* abbrev
320+
* base64
321+
* drb
322+
* debug
323+
* erb
324+
* find
325+
* net-ftp
326+
* net-http
327+
* net-imap
328+
* net-protocol
329+
* open-uri
330+
* optparse
331+
* pp
332+
* prettyprint
333+
* resolv-replace
334+
* resolv
335+
* rinda
336+
* set
337+
* securerandom
338+
* shellwords
339+
* tempfile
340+
* tmpdir
341+
* time
342+
* tsort
343+
* un
344+
* weakref
345+
* digest
346+
* io-nonblock
347+
* io-wait
348+
* nkf
349+
* pathname
350+
* syslog
351+
* win32ole
352+
353+
See [NEWS](https://github.com/ruby/ruby/blob/{{ release.tag }}/NEWS.md)
354+
or [commit logs](https://github.com/ruby/ruby/compare/v2_7_0...{{ release.tag }})
355+
for more details.
356+
357+
With those changes, [{{ release.stats.files_changed }} files changed, {{ release.stats.insertions }} insertions(+), {{ release.stats.deletions }} deletions(-)](https://github.com/ruby/ruby/compare/v2_7_0...{{ release.tag }}#file_bucket)
358+
since Ruby 2.7.0!
359+
360+
> 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
361+
362+
Merry Christmas, Happy Holidays, and enjoy programming with Ruby 3.0!
363+
364+
## Download
365+
366+
* <{{ release.url.gz }}>
367+
368+
SIZE: {{ release.size.gz }}
369+
SHA1: {{ release.sha1.gz }}
370+
SHA256: {{ release.sha256.gz }}
371+
SHA512: {{ release.sha512.gz }}
372+
373+
* <{{ release.url.xz }}>
374+
375+
SIZE: {{ release.size.xz }}
376+
SHA1: {{ release.sha1.xz }}
377+
SHA256: {{ release.sha256.xz }}
378+
SHA512: {{ release.sha512.xz }}
379+
380+
* <{{ release.url.zip }}>
381+
382+
SIZE: {{ release.size.zip }}
383+
SHA1: {{ release.sha1.zip }}
384+
SHA256: {{ release.sha256.zip }}
385+
SHA512: {{ release.sha512.zip }}
386+
387+
## What is Ruby
388+
389+
Ruby was first developed by Matz (Yukihiro Matsumoto) in 1993
390+
and is now developed as Open Source. It runs on multiple platforms
391+
and is used all over the world especially for web development.

0 commit comments

Comments
 (0)