Rust-Helix: helix — write Ruby classes in Rust

Travis Build Status AppVeyor Build Status

Helix

Helix allows you to write Ruby classes in Rust without having to write the glue code yourself.

ruby! {
    class Console {
        def log(string: String) {
            println!("LOG: {}", string);
        }
    }
}
$ rake build
$ bundle exec irb
>> require "console"
>> Console.log("I'm in your Rust")
LOG: I'm in your Rust
 => nil

Why Helix?

Read the Introducing Helix blog post for a quick introduction to the project!

Getting Started

https://usehelix.com/getting_started

Demos

https://usehelix.com/demos

Roadmap

https://usehelix.com/roadmap

Compatibility

Helix has been tested with the following, though other combinations may also work.

  • cargo 0.18.0 (fe7b0cdcf 2017-04-24)
  • rustc 1.17.0 (56124baa9 2017-04-24)
  • ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin16]
  • Bundler version 1.14.6

Contributing

If you'd like to experiment with Helix, you can start with some of the examples in this repository.

Clone and download the Helix repository:

$ git clone https://github.com/tildeio/helix
$ cd helix

Navigate to the console example folder and bundle your Gemfile:

$ cd examples/console
$ bundle install

Run rake irb to build and start irb:

$ bundle exec rake irb

Try running some of the methods defined in examples/console/src/lib.rs:

> c = Console.new
Console { helix: VALUE(0x7fdacc19a6a0) }
 =>
> c.hello
hello
 => nil
> c.loglog('hello', 'world')
hello world
 => nil

Comments

  • Activity Status
    Activity Status

    Apr 5, 2019

    Hey guys,

    I've been playing around with Helix tonight and so far it's been an awesome experience, thank you! I'm concerned about using it for a project however because it doesn't appear to be very actively maintained or worked on. The last commit was 10 months ago and a number of issues and pull requests have been languishing for a while too. Is Helix still going places?

    Reply
  • Re-try Changes in #148
    Re-try Changes in #148

    Jul 30, 2019

    Unfortunately, #148 broke specs when it was merged so I had to revert it. @konstin we'd love to have you take another go at it.

    Reply
  • Miscellaneous attempts to fix Windows builds
    Miscellaneous attempts to fix Windows builds

    Jul 30, 2019

    This still doesn't work. @wycats I'd love your help on this.

    Reply
  • Investigate the safety of using `rb_raise`
    Investigate the safety of using `rb_raise`

    Jul 30, 2019

                                                                                                                                                                                                           
    Reply
  • What is Helix doing that affects performance so much?
    What is Helix doing that affects performance so much?

    Aug 16, 2019

    Hi, I'm exploring Rust as an extension for Ruby for a lot of expensive calculations. I made a project that implements a simple financial algorithm in six ways (Ruby, C, Helix, ruru, FFI). They are all implemented with the minimum viable code to allow Ruby to be able to call a Rust function cash_flow.

    The benchmark for Helix was surprising, and I'm curious what is unique about Helix that causes the function calls to return Ruby so slowly in comparison with the other methods.

    As you can see from the numbers below, helix's iterations per second when called from Ruby are almost half of ruru, C, and Ruby for a simple function:

    Warming up --------------------------------------
             ruby method    203479 i/100ms
     rust helix instance    120885 i/100ms
        rust helix class    121661 i/100ms
          rust ffi class    161558 i/100ms
         rust ruru class    199846 i/100ms
                 c class    221703 i/100ms
    Calculating -------------------------------------
                          iterations per second     total iterations    time
             ruby method  4966573.4 (±6.8%) i/s -   24824438          in 5.022462s
     rust helix instance  1875397.8 (±6.1%) i/s -    9429030          in 5.046921s
        rust helix class  1852779.7 (±5.9%) i/s -    9246236          in 5.008588s
          rust ffi class  3082134.8 (±8.1%) i/s -   15348010          in 5.019943s
         rust ruru class  4275527.6 (±6.2%) i/s -   21383522          in 5.021156s
                 c class  5483016.5 (±6.0%) i/s -   27491172          in 5.032074s
    

    However, when running a criterion benchmark for the function within the Rust repository, the performance is superb:

    Benchmarking cash_flow
    Benchmarking cash_flow: Warming up for 3.0000 s
    Benchmarking cash_flow: Collecting 100 samples in estimated 5.0000 s (955,252,950 iterations)
    Benchmarking cash_flow: Analyzing
    cash_flow               time:   [5.2014 ns 5.2626 ns 5.3245 ns]
    Found 5 outliers among 100 measurements (5.00%)
      5 (5.00%) high mild
    slope  [5.2014 ns 5.3245 ns] R^2            [0.8278649 0.8276527]
    mean   [5.2079 ns 5.3387 ns] std. dev.      [268.40 ps 395.58 ps]
    median [5.1706 ns 5.3213 ns] med. abs. dev. [208.08 ps 356.25 ps]
    

    This is a significant difference between the actual function and whatever Helix is doing to connect Ruby to Rust. Obviously with interop there's going to be some performance drop, but as you can see the other methods were approximately comparable.

    I want to dig deeper into it because Helix was the best API and usability of all of the methods I tried, but I want to know exactly why the performance is inhibited before we implement critical code with it. Any ideas? Thank you!

    Reply
  • trait objects without an explicit `dyn` are deprecated
    trait objects without an explicit `dyn` are deprecated

    Dec 9, 2019

    Noticed this while tinkering

    warning: trait objects without an explicit dyn are deprecated --> src/errors.rs:26:30 | 26 | pub fn from_any(any: Boxany::Any) -> Error { | ^^^^^^^^ help: use dyn: dyn any::Any | = note: #[warn(bare_trait_objects)] on by default

    Reply
  • Fewer allocations by making function signatures take `&CStr`s.
    Fewer allocations by making function signatures take `&CStr`s.

    May 2, 2017

    As discussed in https://github.com/tildeio/helix/pull/76.

    [breaking-change]

    Reply
  • windows build not finding helix_runtime
    windows build not finding helix_runtime

    Apr 27, 2017

    OS Name: Microsoft Windows 7 Enterprise OS Version: 6.1.7601 Service Pack 1 Build 7601

    c:\Dominic\programming\rails\flipper>gem list helix

    *** LOCAL GEMS ***

    helix-rails (0.5.0) helix_runtime (0.5.0)

    c:\Dominic\programming\rails\flipper>rake build Unable to load text_transform/native. Please run rake build Building text_transform rake aborted! HelixRuntime::MissingDllError: Unable to find helix-runtime-0-5-0.dll in $PATH.

    Bug Needs Bug Verification 
    Reply
  • Fix compat with serde_json
    Fix compat with serde_json

    May 15, 2017

    The previous code was relying on the accidental fact that only a single impl of PartialEq existed. serde_json defines another impl of PartialEq, which causes the constraint to be insufficient, which results in a compile error when serde_json is added to a project with Helix.

    This commit forces the VALUE into a usize eagerly, avoiding this inference issue.

    Fixes #93

    h/t @alyssais

    Thanks to @nikomatsakis for helping me figure out the root cause.

    Reply
  • example : cannot load such file -- helix_runtime/native
    example : cannot load such file -- helix_runtime/native

    May 16, 2016

    rust nightly 1.10.0

    $ cd apps/helix/example/console
     cargo build
       Compiling libc v0.2.9
       Compiling libcruby-sys v0.1.0 (file:///vagrant_data/apps/helix/crates/libcruby-sys)
       Compiling cslice v0.1.0 (https://github.com/rustbridge/neon#f28e32c7)
       Compiling helix v0.1.0 (file:///vagrant_data/apps/helix)
       Compiling console v0.1.0 (file:///vagrant_data/apps/helix/examples/console)
    note: link against the following native artifacts when linking against this static library
    note: the order and any duplication can be significant on some platforms, and so may need to be preserved
    note: library: dl
    note: library: pthread
    note: library: gcc_s
    note: library: c
    note: library: m
    note: library: rt
    note: library: util
    
    helix/examples/console$   bundle exec rake irb
    cargo build --release
    gcc -Wl,-force_load,target/release/libconsole.a --shared -Wl,-undefined,dynamic_lookup -o lib/console/native.bundle
    /vagrant_data/apps/helix/ruby/lib/helix_runtime.rb:2:in `require':LoadError: cannot load such file -- helix_runtime/native
    
    Reply
  • gem/bundler error when I run the 'console' workflow in the README
    gem/bundler error when I run the 'console' workflow in the README

    Apr 26, 2017

    Really looking forward to incorporating Rust into my Ruby codebase :)

    I took a look at this section: https://github.com/tildeio/helix#getting-started-with-helix-examples

    I followed the instructions using Ruby 2.4.0 and here's how far I got:

    > bundle exec rake build
    
    
    Building helix runtime
    
    bundle exec rake compile:native
    Could not find gem 'rake-compiler (~> 0.9.7)' in any of the gem sources listed in your Gemfile.
    Run `bundle install` to install missing gems.
    rake aborted!
    Command failed with status (7): [bundle exec rake compile:native...]
    /private/tmp/helix/examples/console/Rakefile:15:in `block (4 levels) in <top (required)>'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler.rb:286:in `block in with_clean_env'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler.rb:521:in `with_env'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler.rb:286:in `with_clean_env'
    /private/tmp/helix/examples/console/Rakefile:14:in `block (3 levels) in <top (required)>'
    /private/tmp/helix/examples/console/Rakefile:12:in `chdir'
    /private/tmp/helix/examples/console/Rakefile:12:in `block (2 levels) in <top (required)>'
    /private/tmp/helix/ruby/lib/helix_runtime/build_task.rb:39:in `block in define'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/cli/exec.rb:74:in `load'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/cli/exec.rb:74:in `kernel_load'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/cli/exec.rb:27:in `run'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/cli.rb:335:in `exec'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/vendor/thor/lib/thor.rb:359:in `dispatch'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/cli.rb:20:in `dispatch'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/vendor/thor/lib/thor/base.rb:440:in `start'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/cli.rb:11:in `start'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/exe/bundle:32:in `block in <top (required)>'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/lib/bundler/friendly_errors.rb:121:in `with_friendly_errors'
    /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.14.6/exe/bundle:24:in `<top (required)>'
    /usr/local/bin/bundle:22:in `load'
    /usr/local/bin/bundle:22:in `<main>'
    Tasks: TOP => build => helix:pre_build
    (See full trace by running task with --trace)
    
    Bug PR Pending 
    Reply
  • Error on rake task (it looks like the cargo bundle builds fine)
    Error on rake task (it looks like the cargo bundle builds fine)

    Sep 17, 2016

    I've already started here: https://github.com/NullVoxPopuli/case_transform/pull/2/files

    Reply