YJIT is an amazing technology, and together with other innovations like object shapes and various GC optimizations, Ruby is becoming seriously fast! Big Ruby shops such as Shopify [1] have been running 3.3 pre-release with YJIT and reporting double digit percentage performance improvements.
Personally I'm really excited about Ruby and its future. I can't wait to start working with Ruby 3.3 and using it on my client's production sites...
[1] https://railsatscale.com/2023-09-18-ruby-3-3-s-yjit-runs-sho...
Edit: add percentage to performance improvements.
The recent irony of the web is anyone that implemented a web app with "slow" ruby and backend rendering now has the fastest page loads compared to bloated front-end web apps backed by actually slow eventually consistent databases that take seconds to load even the tiniest bits of information. I see the spinner GIF far too often while doing menial things on the "modern" web.
For reference:
$ units -1v '1|2 billion reqs/month / 14 servers' 'req/sec/server'
1|2 billion reqs/month / 14 servers = 13.580899 req/sec/server
I always do this when I see large-sounding query counts; a month has a lot of seconds in it, and it’s easier to visualize only one at a time: I can imagine hooking a speaker up to the server and getting a 14Hz buzz, or do a quick mental arithmetic and conclude that we have ~70ms to serve each request. (Though peak RPS is usually more relevant when calculating perf numbers; traffic tends to be lumpy so we need overhead to spare at all other times which makes the average much less impressive-sounding.)What database is on the backend, and is that db serving cached content? What happens if you cache it with e.g. redis to avoid the heavyweight rails ORM stuff?
Do you have granular benchmarks for the db query, requests to other services, and the web processing itself (using artificially pre-cached responses from db and those other services)?
You’re likely in one of two situations as a businesss:
* You’re a struggling startup. Development velocity trumps literally everything. Your server costs are trivial, just turn them up.
* You’re a successful business (maybe in part because you moved fast with Ruby), you can pay down the debt on that absurdly large response. Chunk it, paginate it, remove unnecessary attributes.
You mean like 10% faster, or 10x faster?
Edit: clicked the link; it's 10%. I don't think that's going to make any difference to the perception of Ruby's slowness given that it's on the order of 50-200x slower than "fast" languages like Rust, Java, Go and C++.
The 100x to 200x mainly comes from Rails.
One is scripting language, the other compiled, the difference is huge already there.
a nice ide integrated experience:
https://code.visualstudio.com/docs/languages/ruby#_debugging...
https://github.com/ruby/vscode-rdbg
https://code.visualstudio.com/docs/editor/debugging
heavy metaprogramming in any language is going to be a pain to debug so i'm not sure what you're expecting but there are tools to help. you can also call source_location on some method to figure out where things exist.
The link shows 13-15%.
If I’m going to give it even a second glance, I can’t be seeing “ruby 10,000% slower than Java” for measured use cases.
But one thing that is not mentioned or discussed enough, is Ractor, M:N thread scheduler, Fibre and Async. Especially in the context of Rails. I am wondering if any one are using these features in productions and if you could share any thoughts on the subject.
This is entirely predictable - Ruby does not have a big scientific computing community which happened to depend on every implementation detail of the hosting interpreter.
It is quite common to see "Python" libraries that are just thin bindings layers, they could just as well be "Tcl" libraries for that matter.
Python workloads, with deep pocketed backers, do spend more time inside GPU or C runtime.
Really? What’s so significant with this release?
> But one thing that is not mentioned or discussed enough, is Ractor, M:N thread scheduler, Fibre and Async.
Yes! Ractors deserve more highlighting! It’s a huge feature.
I think the Prism parser update is a standout highlight for me. This is the start of many new static analysis tools for ruby.
It's also significant that RBS type information is starting to be used in IRB autocompletion. Previously RBS has been an interesting experiment but hasn't had much practical use compared to Sorbet.
Ruby seems to now have good answers to non-blocking IO (async fibers) and tooling questions (ruby-lsp). We're starting to see YJIT performance improvements starting to compound with more to come too.
That all seems significant to me. Thanks to everyone involved.
By the way, celery was born as a protocol spec to support multiple languages but never moved past Python. I can't google a quote for that, I remember I saw it years ago in the documentation somewhere.
External systems come with a cost, especially if it's more than a library.
Not sure I can recommend it, but Gearman does fit the bill. There’s client and worker libraries for a dozen languages, including Python3 and Ruby.
A Ruby implementation would probably not be hard.
I don't how much people use this in serious or high performance work but it might be an option.
[1] https://mac.install.guide/ruby/update.html
Just curious, which version manager would you recommend? Previously I recommended asdf, frum, or chruby.
Do other language runtimes do similar things? Creating a thread sounds too heavy, though it might not matter in practice. As per their own benchmark, the overhead is minimal but still not zero.
10000.times {
Addrinfo.getaddrinfo("www.ruby-
lang.org", 80) }
# Before patch: 2.3 sec.
# After ptach: 3.0 sec.
100.times {
URI.open("https://www.ruby-lang.org").read }
# Before patch: 3.36 sec.
# After ptach: 3.40 sec.My impression is that everything was migrated to be asynchronous by default, unlike in Python where all of these operations were reimplemented in the async "color". Is that true?
I find Ruby fascinating yet difficult.
If you’re fluent in Node and Python it should be quite easy to learn. The downside is it’s not going to do anything fundamentally new for you coming from those languages. The upside is mostly aesthetic, Ruby offers and encourages really beautiful ways of expressing code, and it’s neat to experience that.
Add to this also Shopify, Github, Gitlab, Basecamp and some others and you will see that Ruby can be use for more than shell scripting and data munging. Yes they are Rails but Rails is written in Ruby so they are Ruby.
Ruby is also very fun, probably the most fun language I’ve used regularly. That makes it its own reward.
The most interesting part IMO is how it's so similar to Python along many categories, but also so different.
Biggest example is how Ruby just loves Blocks. They're all over the place in the std lib, tons of syntax sugar for them, and countless DSLs built around them. All the standard functional stuff is there in the std lib and has been from very early on, so doing functional-style stuff is really smooth and reads well. In Python, you can technically do most of the same stuff, but it all seems a lot more awkward to write and to read (though maybe just my opinion from doing Ruby first). Python has lambdas, but it doesn't seem to like them much for more than trivial things. But instead functions are first-class everywhere.
This introduction about a framework built with ruby and not ruby itself was necessary because even today, I would guess that 95% of all development with ruby is RoR applications. It's my understanding that ruby rose to prominence mostly because of ruby on rails, now that RoR is in a downward trend I think ruby will follow the same trend until it's reduced to a small community of enthusiasts in the same way that happened to perl.
As for the language itself I can't think of a single reason to opt for ruby over python or typescript. Ruby doesn't do anything better both in terms of language or platform than its already better established competitors.
I'll bite.
Even at the most basic level of built in functions/methods (String, Array, Hash) - I found Ruby's to blow Python's out of the water.
https://ruby-doc.org/core-2.5.1/String.html
https://www.w3schools.com/python/python_ref_string.asp
Even Python's choice of naming and syntax to use these basic functions just hasn't been thought through as much as Ruby's implementation. There's a reason it's called the language of Developer happiness.
Ruby's community I've found is more focused on best engineering practices (like testing) than others, which is perhaps why RSpec and MiniTest are fantastic frameworks. The likes of PyTest doesn't even compare to what those two offer.
Plenty of reason above to use Ruby, and we haven't even got to Rails yet.
And there is a lot more: new conferences, new books and new gems.
(Shameless plug: I curate a newsletter called Short Ruby that covers news from Ruby world every week).
Maybe Ruby is not at the level where is was in 2007-2009 but it is also NOT in a downward trend.
It's really sad if that's the case. What's replacing it (mostly JS/TS everywhere, relying on PaaS) really isn't as fun.
For me, coming from more of a Ruby background, I found Python and Node to not be too hard to understand, and my only nitpick would be on how eggs/packages were managed and dealing with dependancies.
In particular, Python dependancies compared to Ruby dependancies were more challenging initially for me. I’ve grown to appreciate Python indents and find it nice to read, but that was also annoying at first.
Ruby itself is not the issue. The way people and frameworks (looking at you Rails) abuse its mechanics in pursuit of “clean code” drives me crazy. An incredible number of things are downright challenging to debug because of the insane flexibility of Ruby.
I wouldn't use NodeJS to build web-app that fits Rails. NodeJS ecosystem feels like building on a house of cards though.
Python feels alot cleaner, but I wouldn't pick it over Node for web UI automation or Rest API testing.
Shouldn't the default be the number of logical cores? Like Rust's Tokio and countless other M:N runtimes
On paper it’s awkward, but in reality convention and social norms make it rarely an issue.
The global namespace only supporting exactly one version of each gem encourages a health culture of stable ABIs and deprecation periods too. An absolute dream compared to some language ecosystems
Or I'm speaking out of my ear and completely wrong (and I don't know which :D)
If anything Rails autoloading (Zeitwerk really) make it much easier to find where constants come from as it enforce a constant name -> file name convention, so all you need is fuzzy file search.
Ruby imports have always used a single global namespace. I'm not convinced that this is an issue in practice - it's worked just fine for several other languages.
It looks like a big leap, but when you compare the actual speed to _any_ other language you realize Ruby still has many, many percent to go to even be in the same game.
If you look at CPU bound micro-benchmarks like most similar announcements uses, you easily get into the 3x territory: https://railsatscale.com/2023-12-04-ruby-3-3-s-yjit-faster-w...
Where are you seeing 3x improvement?
Because even this graph from your article doesn’t show that, unless you’re comparing JIT vs non-JIT. But JIT has existed for awhile now (not new in 3.3).
https://railsatscale.com/2023-12-04-ruby-3-3-s-yjit-faster-w...