danielpclark / faster_path

Faster Pathname handling for Ruby written in Rust
MIT License
782 stars 33 forks source link

Research and benchmark use of Fiddle from STDLIB #73

Closed danielpclark closed 6 years ago

danielpclark commented 8 years ago

Ruby has a convenient library for better integrating for code with Fiddle which wraps libffi FFI. The whole idea that it wraps the other library seems to me it would take longer to execute the code. It's the whole convenience verses efficiency battle. But as this is just a theory it should be looked into.

Fiddle offers enough benefits to be worth considering.

But if Fiddle is just a wrapper for FFI, then in theory we can do what Fiddle does with FFI ourselves.

mble commented 8 years ago

As a minor correction, Fiddle wraps the C library libffi, rather than the whole FFI gem. They are quite different in terms of implementation.

danielpclark commented 8 years ago

Thank you! Even more reason to look into it :smile:

mble commented 8 years ago

A major downside (in my eyes) with Fiddle is that it does not support boolean return types, at least as included in the standard library. To use is_blank() with Fiddle, I returned an integer and use equality to return the boolean from the method. Needless to say, this resulted in quite a performance drop:

Fiddle
$ ruby -Ilib -Itest test/benches/is_blank_benchmark.rb
[0.000667, 0.000903, 0.000683, 0.000729, 0.000719] 
[0.000670, 0.000713, 0.000695, 0.000686, 0.000691]
[0.000676, 0.000649, 0.000690, 0.000677, 0.000679]
[0.000683, 0.000726, 0.000697, 0.000629, 0.000632]
[0.000923, 0.000676, 0.000686, 0.000684, 0.000690]

FFI
$ ruby -Ilib -Itest test/benches/is_blank_benchmark.rb
[0.000121, 0.000094, 0.000088, 0.000081, 0.000080]
[0.000113, 0.000083, 0.000075, 0.000074, 0.000081]
[0.000112, 0.000075, 0.000084, 0.000077, 0.000072]
[0.000123, 0.000081, 0.000071, 0.000071, 0.000071]
[0.000131, 0.000084, 0.000076, 0.000068, 0.000071]

FFI includes stdbool.h in their implementation to deal with this, which is why it is considerably faster (don't need to get ruby to generate the boolean). I can have a look at the performance of some of the methods that return strings with Fiddle, but the interface isn't particularly friendly.

Longer term, I am of the opinion that something like ruru or helix are the way to go.

danielpclark commented 8 years ago

Thanks for this @mble .

Longer term, I am of the opinion that something like ruru or helix are the way to go.

I'm with you on wanting these nice projects incorporated. What prevented me from using Helix is they don't have enough info on how to get started. That's also the same reason I didn't incorporate ruby-sys.

Now looking at Ruru they seam to be at a point where they're really usable. I even like that I see the use of ruby-sys in it. What they don't show is the Ruby integration. They have as minimal Fiddle example at the end.

Once concern I have to look into in this project is whether the memory for what we're returning from Rust to Ruby is being freed up. This was brought to my attention in #41 . None of these tools listed here cover any of that. Advice on memory management is available in the FFIwiki so that will need to be done soon. I also need to learn some memory diagnostic tools to try with this.

But back on topic I'm totally open to integrating one of these outside projects as long as we benchmark whether there is a cost.

malept commented 8 years ago

What they don't show is the Ruby integration. They have as minimal Fiddle example at the end.

In my experience (I've written two ruru-based extensions so far), that is literally all you have to do with Fiddle to get the extensions working. All of the magic is in the macros plus the initialization function (which really, isn't too different from creating a C-based Ruby extension, except much nicer syntax).

danielpclark commented 8 years ago

You know, since Fiddle is part of the Ruby standard library there wouldn't be any trouble using both. We'd just need to weigh the advantages and disadvantages per use.

danielpclark commented 6 years ago

I've done some benchmarks and enough details were available to make the switch to ruru. See blog post on performance: https://blog.codeship.com/improving-ruby-performance-with-rust/