LoginSignup
1
0

More than 3 years have passed since last update.

「様々な言語でMap, Filter, Reduceを実現してみた」をRust&Rubyでやってみた

Last updated at Posted at 2019-05-15

これは何?

様々な言語でMap, Filter, Reduceを実現してみた(1)の記事を見てRustRubyでやってみたというだけの記事です。

環境

  • MacBook Pro (2018)
  • macOS Mojave 10.14.4
  • rustc 1.34.1
  • ruby 2.6.2p47

コード

※制限事項「生成したデータはイテレータオブジェクトではなく、実体データの集合になるようにした」に則ってコードを修正済み

Rust

fn main() {
    let a = (0..10_000_000).collect::<Vec<i64>>();
    let res = a
        .iter()
        .map(|a| a * 2)
        .filter(|&a| a % 3 == 0)
        .fold(0, |acc, x| acc + x);
    println!("{}", res);
}

Ruby

class Integer
  def twice
    self * 2
  end

  def div3?
    self % 3 == 0
  end
end

a = (0..10_000_000 - 1).to_a
puts a.map(&:twice).select(&:div3?).sum

計測

mfr.rsおよびmfr.rbというファイル名にしました。

Rustの場合

$ cargo b --bin mfr --release
$ time ./target/release/mfr
33333336666666

real    0m0.016s
user    0m0.012s
sys     0m0.003s

環境差異があるとはいえ、元記事C++のケースより速いのはなぜでしょう…?

(追記)ルール違反してた。

  • 生成したデータはイテレータオブジェクトではなく、実体データの集合になるようにした

というわけで、Rangeオブジェクトのままmap/filter/foldするのではなく、一旦Vec<i64>collectしてから実行するように修正。Rubyも同様。

$ time for i in `seq 1 1000`; do ./target/release/mfr ; done
(中略)
33333336666666

real    1m4.037s
user    0m29.641s
sys     0m31.654s

1回あたりの処理にかかる時間はおよそ12msec。標準出力に吐く処理で3msecぐらい(文字列を出力するプログラムで測った)なので、コンパイル時に計算しているわけではなさそうです。

だいたい1処理あたり64msですね。それでも微妙に元記事のC++のケースより少し速い。

Rubyの場合

上記環境での1回の実行で1.9秒ぐらいかかった。

$ time ruby mfr.rb 
33333336666666

real    0m1.946s
user    0m1.777s
sys     0m0.129s
1
0
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0