パフォーマンス的にはどうなのだろう、と思って簡単なスクリプトで測ってみました。
1000000個の要素(すべて 1 )をもつ配列の、全要素の和を求めるだけのスクリプトです(10回繰り返しているのは平均をとるため)。
(環境)
$ruby -v
ruby 1.8.7 (2009-04-08 patchlevel 160) [i686-linux]
for.rb
ary = Array.new(1000000,1)
t = 0
10.times{
time1 = Time.now
sum = 0
for i in 0..ary.size-1
sum += ary[i]
end
time2 = Time.now
t += time2 - time1
}
puts "for : (avg time) #{t / 10} ms"
each.rb
ary = Array.new(1000000,1)
t = 0
10.times{
time1 = Time.now
sum = 0
ary.each{ |elem|
sum += elem
}
time2 = Time.now
t += time2 - time1
}
puts "each : (avg time) #{t / 10} ms"
inject.rb
ary = Array.new(1000000,1)
t = 0
10.times{
time1 = Time.now
sum = ary.inject(0){ |result, elem|
result += elem
}
time2 = Time.now
t += time2 - time1
}
puts "inject : (avg time) #{t / 10} ms"
-- 実行結果 --
$ ruby for.rb
for : (avg time) 0.6509955 ms
$ ruby each.rb
each : (avg time) 0.5049966 ms
$ ruby inject.rb
inject : (avg time) 3.6189753 ms
eachが一番速いのは予想通りとして、測り方間違えた?と思うくらい inject が重い。
では、関数型言語だとどうだろう?と、Gauche (scheme) で書いてみました。こちらは for-each vs fold になります。(平均はとってません...。)
(環境)
$ gosh -V
Gauche scheme interpreter, version 0.8.14 [utf-8,pthreads]
make-list.scm(list作成用)
(define (make-list num)
(let loop ((lis '()) (n num))
(if (eq? 0 n)
lis
(loop (cons 1 lis) (- n 1)))))
for-each.scm
(define lis (make-list 1000000))
(define sum 0)
(time
(for-each (lambda (x) (set! sum (+ sum x))) lis))
fold.scm
(define lis (make-list 1000000))
(time (fold + 0 lis))
-- 実行結果 --
$ gosh for-each.scm
;(time (for-each (lambda (x) (set! sum (+ sum x))) lis))
; real 0.230
; user 0.230
; sys 0.000
$ gosh fold.scm
;(time (fold + 0 lis))
; real 0.620
; user 0.590
; sys 0.030
互角か?と思っていたのですが、Gauche でも for-each のほうが速いようです。
# まぁRubyでこんな巨大な配列を扱うことはないのかも
0 件のコメント:
コメントを投稿