What you need to know about Ruby Interpreter

Using the right Ruby interpreter to run your programs can make all the difference. Unfortunately, it can be tough to find resources about different Ruby interpreter options, or about how to choose the right one.

Below, we’ve compiled a wealth of information about interpreters in Ruby. Even if you start this article asking "What is a Ruby interpreter?", you’ll learn exactly what you need to know to make the right decision.

Why are interpreters important?

Languages are the foundation of communication. They consist of a standard set of vocabulary, grammar, and syntax that two people agree upon to exchange information. When two people don’t speak the same language, however, you need a way to translate or interpret the same ideas from one language to another.

The same concept of translation and interpretation applies to programming languages as well. Machines aren’t automatically able to comprehend the high-level code that humans program in. They can only execute machine code, a limited set of low-level instructions that the computer’s CPU can immediately understand.

Machines have two ways of working with programming languages like Ruby: compilation languages and interpreted languages.

What’s the difference between compiled programming vs. interpreted programming languages?

Compiled programming languages require a tool called a compiler. Before the user can run a program, the compiler must convert the high-level code into a series of low-level instructions in a series of stages. This machine code is specific to the machine that the program is running on.

Interpreted programming languages require a tool called an interpreter. The interpreter converts the source code to machine code line by line, while the program is running.

This difference is like the distinction between translating and interpreting a foreign language. Translators do their work in advance, before the person who needs it will use it. Interpreters perform the translation live, while the person who needs it is listening.

Both compiled languages and interpreted languages have their pros and cons. Some languages such as Java use a mixture of both methods. In general, interpreted languages are more flexible, more portable to different systems, and easier to debug. However, they pay for these advantages by sacrificing speed and performance.

Compiled languages are typically faster than interpreted languages. This is because the compiler has the time it needs to optimize the code for the specific machine that the program is running on.

Although Ruby is more often interpreted, it can be both interpreted and compiled depending on the implementation. In the remainder of this article, we’ll discuss only interpreters for Ruby.

What is a Ruby Interpreter?

A Ruby interpreter is any program that is able to interpret source code written in the Ruby language.

Just like you might use different human translators or interpreters, there’s not a single version of the Ruby interpreter. Instead, there are multiple interpreter options for Ruby developers. Each version imparts a slightly different "flavor" to the language.

So how can you be sure that the interpreter you use is actually running the "real" Ruby? By using the Ruby Spec Suite (also known as ruby/spec). The Ruby Spec Suite is a set of tests to verify that a given Ruby implementation has the correct behavior and results when interpreting a program.

What are the best Ruby Interpreter options?

Below, we’ll discuss the most popular alternatives for Ruby interpreters: YARV, Ruby MRI/CRuby, JRuby, and Rubinius. All of the interpreters below have passed the Ruby Spec Suite and are solid, mature options for running Ruby code.

What is YARV?

YARV (Yet Another Ruby VM) is the stack-based interpreter technology that powers the official interpreter of Ruby. Beginning with Ruby version 1.9, YARV has replaced the old version of Ruby MRI (also known as CRuby). As of Ruby 2.6, YARV remains the official interpreter technology used for Ruby.

When you run a Ruby program, YARV translates the code to a limited instruction set that can run in the Ruby virtual machine (VM). A VM is a program running on your computer that emulates a separate computer to have better predictability and stability. This ensures that all computers can run Ruby regardless of the specific machine code they use.

What is Ruby MRI/CRuby?

Before YARV arrived in Ruby 1.9, the default Ruby interpreter was Ruby MRI, also known as CRuby. Ruby MRI stands for Matz’s Ruby Interpreter (named after "Matz," or Yukihiro Matsumoto, the chief designer of Ruby).

The alternative name, CRuby, reflects the fact that the interpreter is in the C programming language. CRuby differs from YARV under the hood: whereas YARV uses a stack to parse Ruby code, CRuby uses an abstract syntax tree.

What is JRuby?

Just as CRuby was in C, JRuby is a Ruby interpreter in the Java programming language. JRuby follows in the footsteps of other programming languages that run atop the Java Virtual Machine (JVM), such as Clojure and Scala.

Because JRuby uses the JVM, you can run Ruby programs anywhere that you can run Java programs, from laptop computers to Android phones. JRuby can also leverage Java standard and third-party libraries.

What is Rubinius?

Rubinius is an attempt to interpret Ruby programs with as little C code as possible, differentiating itself from Ruby MRI/CRuby. The foundations of Rubinius are in the C++ programming language, while other parts use as much Ruby code as possible.

Rubinius includes a "Just In Time" (JIT) compiler that compiles the code while the program runs, helping it to run more dynamically. This gives it improvements over Ruby MRI in terms of memory management and speed.

Which Ruby Interpreter Should You Use?

The matter of which Ruby interpreter to use is an open-ended question that depends on your specific situation.

If you’ve installed the default version of Ruby, then you’re almost certainly using YARV (if Ruby 1.9 and above) or Ruby MRI (if Ruby 1.8 and below). In many cases, this default option is sufficient for Ruby developers.

However, Rubinius or JRuby may be better if you have high-performance requirements from your Ruby programs. According to one benchmark test, Rubinius and JRuby achieved performances roughly twice as good as Ruby MRI.

Another consideration for which Ruby interpreter to use is the question of threads and parallelism. Ruby MRI uses a feature known as the Global Interpreter Lock (GIL). The GIL prevents multiple program threads from accessing the same data at the same time. By default, Ruby is single-threaded and does not allow for parallelism and multithreading.

However, this restriction is not present in other implementations of the Ruby interpreter, such as Rubinius and JRuby. You can take full advantage of multi-core and multi-CPU systems, significantly boosting performance.

The good news is that the Ruby team wants to bypass the limits of the GIL in the upcoming Ruby 3 release via a mechanism known as Guilds. In the future, you might be able to see some benefits of parallelism and multithreading in the default version of Ruby. However, you’ll have to be patient enough to wait for Ruby 3 (currently without a release date).

Final thoughts on options for Ruby Interpreter

The alternatives listed above are by no means your only options for Ruby implementations. mruby is a Ruby implementation intended for embedded systems such as the Raspberry Pi. Meanwhile, Opal is a compiler that converts Ruby to JavaScript.

For most Ruby use cases, though, you can’t go wrong by choosing one of the following:

To find out more about our Ruby monitoring agent and how it can help you to find performance issues in your Rails applications, then click here.