Help us understand the problem. What is going on with this article?

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

More than 5 years have 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

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away