6 ms·
At my day job have an a prod analytics service with all the stuff you mention written in Rust + PG, and the Rust bit which handles data ingestion via HTTP and J
by ehsanu1 9y ago
At my day job have an a prod analytics service with all the stuff you mention written in Rust + PG, and the Rust bit which handles data ingestion via HTTP and JSON is only about 5x faster than the equivalent Ruby code. Obviously, that was a big disappoitment to me.
5x isn't too shabby for something potentially somewhat IO-bound. Presumably the effort wasn't 5x to build and maintain that, so if that's a very hot inner loop of something that's great.
What I've found is that using Ruby (mainly gems) idiomatically can just lead to way slower performance. Eg I use time libraries a lot for my day job, and the idiomatic way to write the code had tons of hidden costs and was basically impossible to optimize.
So I wrote a ruby extension in rust, and got a 30x speedup on that code - it was pretty computationally intensive, so a perfect fit for this. Part of it was that I was forced to use more primitive types, but in Rust-land I was able to add types all over the primitives and abstract away to my heart's content, without any overhead. That's just something that's impossible in Ruby - each abstraction always has a cost and there's no way around it.
If you look at the work Aaron Patterson and Shaun Griffin have done and are doing on AR, or what Peter Ohler has done with Oj, I don't think it's fair to say that either the Rails or Ruby ecosystem doesn't care about performance. They just don't put it before usability by default.
Right I wouldn't say nobody cares about performance, some people care a lot and they've been doing great work and helping raise the bar. But overall, the bar is pretty low in the Ruby world.
Chris Seaton (one of TruffleRuby's main authors) has a talk where he shows some of the batshit insane code you see in gems, which they had to figure out how to optimize in TruffleRuby/Graal. Code like allocating a new array and calling the `min` method in order to find the smaller of two values! And that was being called in a hot inner loop! In a gem with otherwise great functionality, a nice website and thousands of users. That's the kind of thing you only see in Ruby-land.
Also, using method_missing (gotta have that pretty DSL, performance and greppability/discoverability be damned) and monkey-patching/alias-chaining/etc is still common unfortunately (though a smart JIT, ie Graal, can apparently handle that).
I am really excited about TruffleRuby and it does really amazing things to optimize crazy Ruby code, so I'm looking forward to Ruby being as fast as say JS in the future. Can't wait for the day I can turn on TruffleRuby in production and halve the AWS bill.
- jashmatthews 9y agoBoth are CPU bound on de-serialization. It’s basically DB replication over HTTP plus some business logic at either end. The Sinatra version is built in a weekend which is 5x slower has authentication and does use ActiveRecord. Building an entire web app, with background job processing, in Rust with the ecosystem how it is at the moment is very, very slow compared to Ruby, Sinatra and Sidekiq. When we started Diesel couldn’t join to more than one table. Probably approaching 5x in development time. It’s just not mature enough yet. We’re still experiencing stuck threads which don’t timeout. Sounds like you found a great case for a native extension!
- ehsanu1 9y agoAgreed, I wouldn't do a production web service purely in Rust yet, the ecosystem is still way too immature.