Talks

Opening Keynote: Ruby 3 Today

EuRuKo 2016

00:00:04.319 It's time for the awesome Matz to give us the keynote, so let's get started and welcome him.
00:00:28.960 Welcome to the stage!
00:00:34.530 Giving a keynote in English makes me nervous every time, but I believe I can manage.
00:00:43.600 In recent years, we have been working on something called Ruby 3.
00:00:50.000 Ruby 3 represents the future of Ruby. However, you will not see Ruby 3 this year or next year; it's a vision for the distant future.
00:01:00.039 In that sense, Ruby 3 is currently more of a concept than a reality.
00:01:08.080 Since it is just a vague notion, we must acknowledge that these ideas are fragile, but we need some goals to aim towards in order to advance the Ruby community.
00:01:22.759 Especially for the Ruby community, setting clear goals is essential for progress.
00:01:30.520 A very important aspect of the future Ruby is that it should remain compatible with current Ruby versions.
00:01:40.159 We experienced a huge gap when we transitioned from Ruby 1.8 to 1.9, which was very challenging.
00:01:48.280 We needed to support multiple encodings and better Unicode support during that transition.
00:01:54.880 We want to avoid such pain in the foreseeable future.
00:02:01.119 So, despite the fact that we are trying to introduce many dramatic features in Ruby 3, we will strive to maintain compatibility with the existing versions.
00:02:08.759 The key features of Ruby 3 will focus on performance, concurrency, and typing.
00:02:14.680 For performance, we have a slogan: "Ruby 3 x 3," meaning that Ruby 3 will be three times faster than Ruby 2.
00:02:20.840 That sounds great, right? We are working on optimizing the garbage collection (GC), improving the virtual machine (VM), and other optimizations.
00:02:27.760 We are also investigating the introduction of Just-In-Time (JIT) compilation to the Ruby virtual machine.
00:02:35.720 However, making Ruby three times faster is not an easy task.
00:02:42.000 We've been developing Ruby and its interpreters for more than 20 years, and we have already optimized many easy targets.
00:02:49.080 Because of that, achieving a threefold increase in speed will be quite a challenge.
00:03:04.120 We compare Ruby 3 to Ruby 2.0, which is a version that's about three years old, and we've improved Ruby consistently.
00:03:17.840 For instance, each year since Ruby 2.0, we've introduced improvements at a rate of 5 to 10%.
00:03:30.040 Each version is designed to be faster than the previous one.
00:03:41.880 Hence, we aim to include all of those efforts in Ruby 3, even though not everything can be three times faster.
00:03:56.600 We will choose specific benchmarks where Ruby 3 will run faster than Ruby 2.
00:04:01.360 These benchmarks will be small; we don't want to install large frameworks or huge applications for testing.
00:04:07.159 However, they should not be overly simplistic, like calculating factorials.
00:04:15.360 We want realistic benchmarks that reflect actual performance improvements.
00:04:24.240 Now, let's discuss concurrency. I started designing Ruby in 1993, and back then, computers only had one CPU.
00:04:40.360 That meant we didn’t have to worry about threading or parallelism since there was only one execution thread at a time.
00:04:55.360 Because of that, I only considered concurrency and added threading to the language.
00:05:01.360 But I didn't give much thought to parallelism.
00:05:07.360 Today, however, we are living in a multi-core age with dual-core, quad-core, and octa-core CPUs in laptops and smartphones.
00:05:14.400 Everyone wants to leverage concurrency and parallelism.
00:05:20.960 People want to utilize concurrency and parallelism through threading.
00:05:29.759 But we face challenges with threading, especially in Ruby, due to the Global Interpreter Lock (GIL).
00:05:37.560 Due to the GIL, only one thread can run at a time in the Ruby virtual machine.
00:05:43.000 So, there is no true parallelism, even on multi-core machines.
00:05:55.360 This creates a trade-off between performance and safety. Multicore machines can perform better, but threading introduces complexity.
00:06:03.600 Managing threads independently while ensuring synchronization is quite challenging.
00:06:09.440 By changing a few lines of code, it's possible to remove the GIL from the Ruby virtual machine.
00:06:16.000 However, your threaded program will likely crash if you try that.
00:06:25.360 We prioritize safety in the Ruby virtual machine.
00:06:32.000 Threading can be considerably complex without the right language features, unlike languages like Elixir.
00:06:42.000 For this reason, we concluded we need better abstractions for concurrency.
00:06:54.399 We investigated various models: the actor model, streaming model, and ownership model.
00:07:05.760 Last year, I discussed the concurrency topic in my keynote, particularly focusing on the streaming model.
00:07:12.800 However, we decided to abandon the streaming model and have opted for a form of the ownership model with slight modifications.
00:07:24.880 This model needs a name, so we are looking for a suitable term.
00:07:35.320 Kichi, who is in charge of the virtual machine, has been searching for this concept for years.
00:07:49.600 Finally, we came up with a name for this idea: ‘Guild.’
00:07:55.080 A guild represents a community of craftsmanship, reminiscent of role-playing games.
00:08:01.320 In this guild model, each object is a member of a guild, and you can transfer the membership of an object to another guild.
00:08:14.479 However, objects must be moved instead of copied, and such transfers can occur via channels.
00:08:21.040 Think of it like goroutines, with some abstractions layered on top of the current Ruby model.
00:08:28.000 It resembles the actor model and shares minimal mutable state.
00:08:37.360 While classes and modules can be shared, we will still have the GIL.
00:08:45.760 Each guild is isolated, allowing multiple guilds to run in parallel.
00:08:55.360 Within a guild, you can still have threads, but only one thread can run at a time.
00:09:06.320 This concurrency model ensures that different guilds can execute in parallel, enhancing performance.
00:09:17.320 We provide a better abstraction for concurrency while maintaining compatibility.
00:09:24.000 This approach should reduce bugs in the system.
00:09:35.120 We've moved away from the streaming model and instead experimented with that model in another language I created called Stream.
00:09:43.079 This is my personal toy language featuring the streaming model available on GitHub.
00:09:55.599 Now, let’s move on to the final and biggest topic of this keynote: typing.
00:10:03.680 In this decade, we have seen the rise of many new programming languages, most of which are statically typed.
00:10:14.000 Examples include TypeScript, Flow, Go, and Swift. Statically typed languages have gained a lot of popularity.
00:10:27.520 I often hear hostile claims that Ruby is dead because it lacks static typing.
00:10:36.239 Who really cares? We should not be swayed by technological trends that come and go.
00:10:45.680 For example, during the 1980s, dynamically typed programming languages like Lisp and Smalltalk were very popular.
00:10:55.840 Eventually, many developers shifted towards statically typed object-oriented languages like Java.
00:11:04.560 Yet, some developers from the Java world later transitioned to Ruby and JavaScript.
00:11:12.960 And now we see some of those developers moving toward statically typed languages like Swift and Go.
00:11:25.600 This cycle of migration happens roughly every decade.
00:11:33.840 What does the future hold? It's possible that we will see a shift towards statically typed languages again.
00:11:46.239 As front-liners, we must think about the future of dynamic typing.
00:11:53.440 So, what does typing mean in dynamically typed programming languages like Ruby?
00:12:00.239 In statically typed languages, a class is a type, but in Ruby, the class is not necessarily a type.
00:12:10.680 We have a principle called duck typing.
00:12:18.960 Duck typing suggests that if something behaves like a duck, it is treated as a duck.
00:12:28.320 In other words, we ignore inheritance or internal structure and focus on behavior.
00:12:37.440 In Ruby, we care about how things behave rather than the details of how they are implemented.
00:12:45.520 Thus, duck typing is the Ruby way, where simplicity and ease of use are prioritized.
00:12:52.400 Dynamic typing allows us to ignore unnecessary formalities and reduces cognitive load.
00:13:02.640 Our mental resources are limited, so we should conserve them.
00:13:10.080 For example, when we need a logging function, we might use a string to log messages.
00:13:19.920 In a statically typed version, we might need to provide type annotations.
00:13:27.920 But in Ruby, we can create a StringIO to log messages and retrieve them easily.
00:13:34.800 However, in the static typed world, that would fail because StringIO and other types do not share a common ancestor.
00:13:41.680 This is where duck typing shines: it allows flexibility and reduces mental costs when developing programs.
00:13:49.600 Furthermore, duck typing leaves room for ambiguity, making it easier to represent behaviors without strict rules.
00:13:58.440 In Ruby, a type is not nominal; instead, it's defined by the expected behavior.
00:14:06.240 We don't need exact names or strict inheritance hierarchies.
00:14:16.080 Although we can call for more expressive interfaces, that often causes unnecessary limitations.
00:14:23.360 In Ruby, we prioritize 'Don't Repeat Yourself' (DRY), which means avoiding redundancy.
00:14:36.640 If you can execute a program without some factors, you should remove them.
00:14:48.320 Currently, dynamic typing implies that we don’t need to repeat type annotations.
00:15:01.120 While dynamic typing has its downsides, such as discovering errors only at runtime, this can promote better development practices.
00:15:10.240 Nonetheless, dynamically typed languages often produce less clear error messages.
00:15:20.400 For example, receiving an error message like ‘undefined method for a new class' can be frustrating.
00:15:31.760 With class annotations, documentation suffers as well, as we often only provide type information in comments.
00:15:42.560 While static typing can be productive, it contradicts the essence of Ruby.
00:15:51.040 While it would look like we are incorporating static typing without truly enforcing it, the essence of Ruby lies in its flexibility.
00:16:00.320 As engineers, our goal is to find solutions without unnecessary complications.
00:16:11.320 One solution is type inference, seen in languages such as Scala or OCaml.
00:16:18.320 Type inference allows the compiler to determine variable types without explicit annotations.
00:16:26.320 This strikes a balance between flexibility and type safety.
00:16:34.320 The compiler can catch more errors during compile time, combining the benefits of dynamic and static typing.
00:16:41.760 For instance, we can simplify the Go interface example with inferred types, which closely resembles Ruby's dynamic typing.
00:16:50.240 This gives us a sense of dynamic inference, defined by behavior instead of strict naming.
00:16:59.440 In Ruby, inferred types are not necessarily linked to class names; they represent expected behavior.
00:17:05.680 However, inference isn't perfect. For example, we may encounter situations where one object conforms to a type but lacks others.
00:17:14.240 Duck typing doesn't guarantee full coverage like suggestive static typing can in other languages.
00:17:22.960 Still, we achieve more reliable typing in Ruby through inference, reducing the chances of error at runtime.
00:17:30.720 We can incorporate ad-hoc type information for error detection, allowing runtime analysis.
00:17:38.720 By combining known type behaviors from specific objects, we can check type compatibility.
00:17:46.400 For example, if a method requires a particular type of argument, the system should recognize this and provide feedback.
00:17:55.040 Also, runtime type information allows for more profound insights, improving the developer experience.
00:18:04.480 By collecting data on argument types, we can create a type database for our applications.
00:18:12.800 This knowledge can enhance our coding experience, enabling better productivity tools in the future.
00:18:20.640 This is still in the conceptual phase, but we're actively researching these improvements.
00:18:30.160 It's crucial for Ruby to keep evolving. Many older languages have stagnated, leading to diminishing communities.
00:18:39.440 I don't want that for the Ruby community; I want it to flourish. Ruby needs to progress to avoid stagnation.
00:18:46.800 We need motivation and a driving force to continue moving forward.
00:18:55.040 The primary motivation behind Ruby 3 is to enhance productivity and enjoyment in programming.
00:19:04.160 We care about programmers and their experiences while using Ruby.
00:19:11.680 The question on your minds might be: when will all of this be available?
00:19:18.800 The short answer is: I don't know.
00:19:26.800 The longer answer suggests that it will take years.
00:19:33.840 We have a lot of work ahead with duck typing, Ruby 3 x 3, guilds, and other features.
00:19:42.560 You may need to wait a couple of years, unfortunately, but we welcome your feedback and contributions.
00:19:54.080 We want your input to help us continue moving forward in the Ruby community.
00:20:01.840 Each Ruby user and developer can contribute to Ruby’s growth.
00:20:10.320 This is perhaps the most important message and motivation behind the Ruby 3 project.
00:20:19.760 Let’s embrace programming in Ruby, enjoy it, and focus on improving our ecosystems.
00:20:28.560 Together, we can strive to become better programmers.
00:20:36.760 This concludes my keynote. Thank you, and happy hacking!
00:20:53.920 Thank you, Matz.
00:20:54.960 [End of transcript]