RubyからRustの関数をつかう → はやい

  • 39
    Like
  • 0
    Comment
More than 1 year has passed since last update.

この記事ではruby 2.2.3とrustc 1.4.0を使用しています。

すごい要約

とのことです。

Rust、はやい

最初にRubyとRustの計算速度を比べるため、フィボナッチ数を単純に計算するやつをそれぞれ書きました。

fib.rb
def fib(n)
  return n if n <= 1
  fib(n - 1) + fib(n - 2)
end

puts fib(40)
main.rs
fn fib(n: u32) -> u32 {
    if n <= 1 {
        n
    } else {
        fib(n - 1) + fib(n - 2)
    }
}

fn main() {
    println!("{}", fib(40));
}

実行結果は以下です。

Ruby
$ time ruby fib.rb
102334155

real    0m12.538s
user    0m12.462s
sys     0m0.047s
Rust
$ time cargo run
102334155

real    0m1.468s
user    0m1.398s
sys     0m0.063s
ビルド済みRust
$ time ./target/release/fib
102334155

real    0m0.517s
user    0m0.514s
sys     0m0.002s

この処理だとRustの方がはやいようです。

Rustを共有ライブラリにする

RustをShared LibraryとしてコンパイルしてRubyから呼ぶために以下の変更を加えます。

lib.rs
#[no_mangle]
pub extern fn fib(n: u32) -> u32 {
    if n <= 1 {
        n
    } else {
        fib(n - 1) + fib(n - 2)
    }
}
Cargo.toml
[lib]
name = "fib"
crate-type = ["dylib"]

ビルドします。

$ cargo build --release

target/release 以下に libfib.dylib が生成されていたら成功です。

RubyからRustの関数を呼ぶ

事前に ffi をインストールしてください。

rust-fib.rb
require "ffi"

module Fib
  extend FFI::Library
  ffi_lib 'target/release/libfib.dylib'
  attach_function :fib, [:uint], :uint
end

puts Fib.fib(40)

Ruby meets Rust

速度の計測です。

Ruby Ruby + Rust Ruby + Go
13.311s 0.629s 0.725s
13.262s 0.639s 0.723s
13.621s 0.621s 0.720s

どの言語も仲良くやっていくのが平和でよいなと思いました。