11 ms·
Improving Ruby Performance with Rust
- yarapavan 9y agogithub code repo used in the article: https://github.com/danielpclark/bench_ruby_ffi_example https://github.com/danielpclark/bench_ruby_ffi_example
- rubyfan 9y agoI might have missed it but is there a particular advantage Rust has over C in this specific use case? Performance, ease of interoperability, etc. or is it preference for Rust over C?
- unrealhoang 9y agoSafety, I guess. A Ruby developer will likely to shoot themselves in the foot with C's freedom. They can use help from Rust's guidance system.
- vvanders 9y agoRust also has a much nicer package ecosystem. It's pretty trivial to wrap existing C libraries as well so I find that I can get up and running much faster rather than messing around with makefiles.
- bpicolo 9y agoYeah, this is the killer feature. cmake is a nightmare. Cargo does what it needs to do and gets out of your way, and provides easy access to the whole ecosystem.
- deleted 9y ago[deleted]
- biokoda 9y agoHistory has proven that anyone no matter their abilities is going to shoot themselves in the foot regularly while using C. Some just less frequently.
- currymj 9y agoThere are lots of advantages in general, especially around multithreaded code, and doubly so for anything with relatively simple data parallelism, where you can just use the rayon library. Another advantage is that there are Rust packages for Ruby interop -- the article ended up using ruru. There are similar libraries for Python interop -- I believe the most actively developed right now is PyO3. I'm sure people are sick of Rust evangelists on HN but it really is a wonderful language, and in certain cases it really does seem to empower people to do things they wouldn't have been able to do otherwise.
- vvanders 9y agoNot just Ruby, Python too. Was doing some work of converting [0,1] signals to 16-bit PCM data with 550Hz tone in numpy. Python version took ~15 minutes to generate 5,000 4 second files. Broke out the inner loop into Rust with FFI via ctypes and cut that time to ~10 seconds with nearly identical code.
- gravypod 9y agoHave you tried using Julia for this task? It's compiled and provides many of the math-y facilities you'll need for something like this (I'd assume).
- vvanders 9y agoYeah, I've heard of Julia before but looks like it doesn't have a very clean[1] FFI story. I'm not super-interested in spinning up a full-blown interpreter for an inner loop. Plus I already had Rust installed :). Seriously though Rust was 43 lines of code + cargo build vs 33 lines of Python and a simple C FFI so it was pretty straightforward to drop in. https://docs.julialang.org/en/release-0.4/manual/embedding/ https://docs.julialang.org/en/release-0.4/manual/embedding/
- chroem- 9y agoI think the whole idea behind using Julia in this situation would be that you get good enough performance "out of the box" so that you don't have to resort to using an FFI in the first place.
- vvanders 9y agoBut that's also the brilliance of Rust supporting a clean C ABI. I can write in anything I want since every language supports C ABI for system calls. I don't want to have to learn a whole new language and new API at the same time. Also a cursory glance at Julia's numpy support looks like it requires deep copies which is painful when you want things to be fast. I'm sure it's a great language but needing to drag in a whole new VM means it doesn't fit my needs.
- rqs 9y agoSorry for my ignorance, but since you already doing Rust, why not just use Rust? I mean, what's the benefit you could get from FFI Rust code into Ruby that you cannot get by directly writing Rust?
- ajmurmann 9y agoIt's a lot easier to write Ruby. For lots of things Ruby also had much more mature libraries. Of course there are other benefits to writing everything in Rust as well. Everything is a trade off. It's quite disappointing . I would have liked free lunch...
- kenhwang 9y agoBy avoiding rewriting all of an existing ruby project too. This way you can just speed up the slow parts and convert piecemeal when necessary.
- rapsey 9y agoRust is a fantastic C replacement. It is nowhere near being a replacement for higher level languages in terms of productivity and ease of use.
- adamnemecek 9y agoNot quite. Rust embraces "zero cost abstractions" which means you can build up pretty high level abstractions without losing any speed. TBH I would much rather write Rust vs Ruby.
- rapsey 9y agoI'm talking about developer productivity not computing efficiency. Those high level abstractions are nowhere near as easy to use or easy to understand as they are in higher level languages.
- adamnemecek 9y agoThey are related. I can build higher abstractions in rust than in ruby.
- andrewfromx 9y agowhere is rust full implementation of ruby on this list? https://github.com/cogitator/ruby-implementations/wiki/List-of-Ruby-implementations https://github.com/cogitator/ruby-implementations/wiki/List-... does such a thing just not exist yet? Let's built it tonight!
- kibwen 9y agoRather than building from scratch, you'd probably just want to start by replacing bits of MRI with Rust one component at a time (assuming MRI is appropriately modularized) and see how far that takes you. :P
- steveklabnik 9y agoHi http://www.codemesh.io/codemesh2016/steve-klabnik http://www.codemesh.io/codemesh2016/steve-klabnik ;) https://github.com/steveklabnik/ruby/tree/rust https://github.com/steveklabnik/ruby/tree/rust
- turboladen 9y agoDoes anyone know of ruru’s status? I’ve used it quite a bit and love it, but haven’t seen any action in the repo in a while. I also pinged the Gitter channel a few weeks ago on the topic and got no response. Its a great tool; would hate to see it die.
- steveklabnik 9y agoThe maintainer is in and out, life happens.
- pmontra 9y agoIf one needs speed one does everything it takes. That said, I read the code of the example. It's short and even if I don't know Rust I've been paid to write C in the 90s. They look similar enough. I see we're back to stuff like let ptr = path.as_ptr(); let c = unsafe { *ptr.offset(i) }; if c == SEP { return &path[(i + 1) as usize..end]; }; It's as low level as it can get. I remember that I wrote a small web app in C in 1994 but I wrote the next one in Perl and never looked back. It was some hundreds lines, countless core dumps and many hours vs much less code and pain and time. Again, Ruby and Python are all about connecting those small pieces of C code that implement their builtin and library methods / functions. Writing them in C or Rust makes no difference. I personally won't write code in those kind of languages again unless I find myself in a scenario where CPU time is worth more than my time. Maybe we'll be back to that with functions in the cloud billed by the millisecond. Programming is going to be a pain again. At least modern languages like Rust don't crash like C and have a better concurrency story. Meanwhile I'll keep using Ruby and Python with C or Rust extensions from GitHub written by somebody else (a big thank you!), and Elixir where concurrency matters.
- sambe 9y agoThe real Rust basename implementation is not so low-level: https://doc.rust-lang.org/src/std/path.rs.html#1801-1808 https://doc.rust-lang.org/src/std/path.rs.html#1801-1808 I don't see how Rust vs C makes no difference. Both languages have trade-offs and I'm pretty sure that Rust advocates would claim the increased safety of the Rust part as a big advantage, and it will certainly reduce those core dumps. Probably the reason there are so many of those advocates is because they don't have to write such error-prone low-level code. Expressive code is more fun, in my experience.
- rapsey 9y agoOf course it looks like C, it's using a C interface to interface with Ruby. Normal Rust does not look like that. Your comment is quite frankly entirely pointless.
- whyever 9y agoYour comment is misleading. The code in question is inside a function of the signature extract_last_path_segment(&str, &str) This is pure Rust, no C interface involved.
- jlebrech 9y agoI wrote a script in Go and used it in ruby with popen3.
- iamleppert 9y agoAm I really reading it right that he went to the trouble of doing all this to speed up the string parsing of file paths??? Talk about barking up the wrong tree. I guess its cool to use something as hipster as Rust to speed up as something as hipster (albeit waning in popularity these days) as Ruby. However, a better approach would be a straight forward implementation of caching (memcache/redis/static CDN) or to simply rewrite that part of the code to not rely on constantly parsing file paths? Or use something like https://github.com/google/re2 https://github.com/google/re2, you probably won't be able to do any better than that when doing any kind of string matching and parsing. If you're concerned at all about performance you shouldn't be doing anything with the file system period.
- kroltan 9y agoIf one is to write such simple code in unsafe mode, might as well just use C! We have https://doc.rust-lang.org/std/primitive.str.html#method.as_bytes https://doc.rust-lang.org/std/primitive.str.html#method.as_b... for accessing a str bytewise. No need for pointers and `unsafe`. The whole point of Rust is being safer and higher-level than C, and if you don't want to use its features, there is no improvement over C.
- Doctor_Fegg 9y agoIn a similar vein: https://github.com/phoffer/crystalized_ruby https://github.com/phoffer/crystalized_ruby Write the speed-sensitive bits in Crystal. Aka 'Improving Ruby Performance with Almost-Ruby'. (Unfortunately development seems to have stopped.)
- prh8 9y agoAuthor here. Development is indeed on hold for now. However, Crystal core team has plans to build a DSL into Crystal to allow for creating Ruby native extensions. There are some technical limitations with how I handled defining functions, which has also become obsolete with recent changes to Crystal. However, there is another approach (macro based) demonstrated at https://github.com/spalladino/crystal-ruby_exts https://github.com/spalladino/crystal-ruby_exts. The macro approach is what is needed. At time of first development, this was just an experiment and I didn't feel like redo-ing it this way. Now that core team has plans for similar functionality, I'd rather not finish a half baked solution that distracts from what theirs will likely be.
- Doctor_Fegg 9y agoVery intriguing. Look forward to seeing what the core team do.
- deleted 9y ago[deleted]