Ruby 2.6: the JIT preview and endless ranges
Ruby 2.6.0 ships on Christmas Day with the first step toward a JIT compiler — a big deal for Ruby's future — plus endless ranges, then as an alias for yield_self, and Bundler in the standard library. A practical tour.
Ruby 2.6.0 has arrived on Christmas Day, and while the everyday additions are pleasant as usual, the headline is strategically significant: Ruby gets its first JIT compiler, as an experimental preview. It is not yet a reason to upgrade on its own, but it is the first visible step of a multi-year effort to make Ruby substantially faster — the foundation of the famous “Ruby 3x3” goal. Here is the tour, headlined by what it means for the language’s future.
MJIT: the first step toward a faster Ruby
The big news is MJIT, Ruby’s first just-in-time compiler, arriving as an experimental, opt-in preview. A JIT compiles frequently-run code to native machine code at runtime, and it is the central technique behind making interpreted languages fast. Ruby’s approach is unusual and pragmatic: MJIT writes C code to disk and uses the system C compiler to compile hot methods into shared libraries that the VM then loads.
ruby --jit my_program.rb # opt in to the JIT
The honest assessment for 2.6: MJIT is not yet a win for typical Rails apps. It currently helps CPU-bound, computation-heavy workloads, while Rails apps — which are dominated by I/O, method dispatch, and memory allocation rather than tight numeric loops — see little benefit and sometimes a regression. So you do not turn it on in production today. Its importance is as a beginning: it is the visible start of the “Ruby 3x3” ambition (Ruby 3 being three times faster than Ruby 2), and over the next few releases this is where Ruby’s performance story will be written. Worth watching closely, not deploying yet.
Endless ranges
A small, genuinely handy syntax addition: ranges with no upper bound, (n..). They read
naturally and clean up common patterns:
# "everything from index 2 onward"
items[2..] # was items[2..-1]
# an open-ended condition in a case
case score
when 90.. then "A"
when 70.. then "B"
else "C"
end
# scopes / comparisons reading "n or more"
ages.select { |a| (18..).cover?(a) }
array[2..] to mean “from index 2 to the end” is clearer than the slightly cryptic array[2..-1]
everyone learned, and endless ranges shine in case/when for “this threshold or above”. A minor
feature you will adopt without thinking about it.
then: a readable name for yield_self
Ruby 2.5 introduced yield_self — the pipe-like method that yields the receiver to a block — but
its name was clunky. 2.6 adds then as an alias, and it reads far better:
# the same value-pipeline, now legible
config
.then { |c| build_url(c) }
.then { |u| fetch(u) }
.then { |r| parse(r) }
Same capability, much nicer name. then makes the “take this value, then do this, then this”
pipeline read like English, and it is the form you will reach for over yield_self from now on.
Collection and Enumerable additions
A useful batch of methods for working with collections:
Array#union,#difference,#intersectiongive named, readable alternatives to the symbolic set operators (|,-,&) and, unlike the operators, accept multiple arguments:a.union(b, c).Enumerable#chainlazily concatenates enumerables into one without building an intermediate array —(1..3).chain([4, 5]).each { ... }— handy for iterating several collections as one.Enumerable#filterarrives as an alias forselect, aligning Ruby’s naming with the term most other languages use.
None is profound, but each replaces a small idiom with a clearer method.
Bundler in the standard library
A quietly significant change for the ecosystem: Bundler is now bundled with Ruby as part of the standard library. Bundler has been the universal dependency manager for years, but it was a separate gem you installed; making it part of Ruby itself recognises that reality and smooths setup — a fresh Ruby install now comes with the dependency tooling every project uses, with no extra step. Small, but it removes a paper-cut from onboarding and CI.
The smaller additions
Rounding out the release: Kernel#then as covered; Proc#call and block-passing get
faster (continuing the steady performance work); constant assignment can be made to raise on
redefinition, helping catch accidental constant clobbering; and the usual round of standard
-library refinements and deprecations. The minimum nothing-dramatic housekeeping continues.
Should you upgrade?
Yes for the language features, no rush for the JIT. The everyday additions — endless ranges,
then, the collection methods, Bundler in stdlib — are pleasant, additive, and risk-free, so you
adopt them naturally. The JIT is the one not to deploy yet: it is an experimental preview that
does not help (and can hurt) typical Rails workloads in 2.6, so leave it off in production for now.
But understand its significance — it is the opening move of Ruby’s multi-year push to be
dramatically faster, the “3x3” goal made visible. Upgrade for the ergonomics today, and watch the
JIT mature over the next releases, because that is where the interesting performance story is about
to unfold. A characteristically practical Christmas release, with a strategically important seed
planted inside it.