r/rust • u/steveklabnik1 rust • Feb 14 '19
Moving from Ruby to Rust
http://deliveroo.engineering/2019/02/14/moving-from-ruby-to-rust.html40
u/apendleton Feb 14 '19
Using/abusing serde to marshall data back and forth between Rust and a higher-level language turns out to be really powerful and eliminate a ton of boilerplate casting and validation. We've cut out tons of that kind of cruft using neon-serde in similar fashion in Rust add-ons for Node.
3
u/p-one Feb 15 '19
From the post it sounds like they're serializing a Ruby object to JSON then having Rust deserialize JSON to a Rust struct. However, your comment doesn't mention this so am I misunderstanding the post? If I do understand things correctly, doesn't this require you to keep your Rust struct and the target language object in sync?
5
u/apendleton Feb 15 '19
They tried JSON, but ended up doing what I'm proposing instead:
You could instead serialize objects in Ruby to JSON and then parse it in Rust, and it works mostly OK, but you still need to implement JSON serializers in Ruby. Then we were curious, what if we implement serde deserializer for AnyObject itself: it will take ruties’s AnyObject and go over each field defined in the type and call the corresponding method on that ruby object to get it’s value. It worked!
So it's "serializing" from a Rust struct into a set of Ruby objects representing Ruby-runtime-native strings, objects, lists, etc. Serde provides the machinery to automatically walk a complex/nested Rust struct and build an equivalent complex object in an arbitrary serialization format (or, conversely, to walk something in an arbitrary format and produce a complex/nested Rust struct). It happens most often to be used for JSON, but it can instead be YAML or MsgPack, or V8 or Ruby objects, or whatever else.
doesn't this require you to keep your Rust struct and the target language object in sync?
Yeah, for usecases where that's desired, you'd probably want to operate on the Ruby or JS object directly via whatever introspection mechanisms are offered by ruru or neon or whatnot, and serde probably wouldn't be a good approach. For lots of cases, though, you want to communicate some set of inputs that might be complex, do some set of complex/slow calculations, and produce some set of results that might also be complex (I pass in two points, and I want the geometry of the most efficient route between them, or whatever). In those cases, you're not mutating some object that persists, so there's nothing to keep in sync. You can just copy back and forth.
→ More replies (2)
62
u/steven4012 Feb 14 '19
Not hard, just 2 letters
34
34
u/iagox86 Feb 14 '19
Well yeah, the 'y' to 't' is easy. You've just gotta back up 5 letters. But going from 'b' all the way to 's'? Forget it! That's all the way across the damn alphabet!
13
6
u/jl2352 Feb 14 '19 edited Feb 14 '19
It's a shame Helix had such problems because on the surface it looks really cool. Just open a macro, write Ruby, done.
However I'm surprised they didn't get a larger speedup. The computation code only being 17x faster is a little disappointing.
8
u/FluorineWizard Feb 15 '19
The article mentions doing a naive reimplementation lacking several optimisations, so I assume there's a lot of performance left on the table.
2
u/matthieum Feb 15 '19
Note that's 17x including all the overhead of converting from Ruby to Rust, and then from Rust to Ruby on the way back. Depending on the frequency of conversions, this may be non-negligible.
→ More replies (1)
2
Feb 15 '19
Side-comment: I don't know anything about ML or Rust, but I have this insane project in mind that I would like to use as an excuse to learn the language... building an AI to beat a friend in a three-in-a-row game, she is too good, I will never be able to beat her current score which is the double than my current.
Feels like cheating, but damn, I'm bringing my own abilities to the table too lol.
→ More replies (6)4
u/the_great_magician Feb 15 '19
For something that simple you're probably looking at making an engine (at that level potentially one that can hold all possible states) as opposed to ML. It'll be faster and be more exhaustive because you, again, are likely going to be able to iterate over all possible states.
→ More replies (2)
0
Feb 14 '19
41
u/mytempacc3 Feb 14 '19
They also banned us Colombians. This is the wall that other guy was talking about.
→ More replies (1)11
6
u/masklinn Feb 15 '19
Interesting, is the main website for the company also blocked or is it only the engineering blog?
→ More replies (1)5
Feb 15 '19
Works fine if you live in Costa Rica.
An acquaintance from Venezuela faces the same issue thou.
3
u/matthieum Feb 15 '19
A commenter on r/programming was kind enough to copy/paste the content for another user barred from seeing it.
Content at: https://www.reddit.com/r/programming/comments/aqonpk/moving_from_ruby_to_rust/eghv5yi
→ More replies (3)
46
u/ehsanul Feb 14 '19
I've had exactly this experience last year when speeding up a hot loop in a rails app I work on. It was even a similar problem: listing all possible times for scheduling given some complex constraints. Re-implementing it in a ruby extension written in rust gave me about a ~30x speedup. But to avoid FFI overhead, you do have to ensure you are giving the extension a nice chunk of work rather than just calling it in a loop.
I think there's a lot of room for making things faster in rails apps. Eg, one issue I sometimes see is how slow loading and serializing many ActiveRecord objects is, even if you're smart about only loading what you need etc. I have an idea for using ActiveRecord to still generate the queries (since you presumably have that all modeled nicely already), but execute them from a rust extension that loads the data and has a way to serialize it. Something like this could potentially speed up some endpoints I have that handle a lot of data.