List performance: ruby 1.8 and 1.9 (Part 1)

(本文数据较多,在rss reader里面可能可读性不是很好,可考虑直接在线阅读)

昨天看到pipitu这篇blog,觉得蛮有意思,文章比较了python和java的list performance,只可惜没有include ruby 1.8和ruby 1.9,不然结论会更有悬念一点,呵呵.

由于无法营造一致的软硬件环境,也不愿意重复pipitu关于python和java部分的工作,这里就只好先简单benchmark(如果可以算是的话)一下ruby 1.8和1.9里的list (array) performance了,也许pipitu以后有空更新include ruby也说不定:)

先看一下我们用的ruby的版本:

$ ruby -v
ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin9]
$ ruby1.9 -v
ruby 1.9.1p376 (2009-12-07 revision 26041) [i386-darwin9]

还有os:

$ uname -a
Darwin macbook.local 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386


benchmark的方法和pipitu的python sample类似,就是往空的list里面循环n次append,由于循环也被引入,其performance也值得考虑,因为众所周知ruby里面做一件事犹如孔乙己的茴字写法一样有n种办法,其performance也各不一样,说不定pipitu以后会和python, java进行横向,咱还是挑相对快一点的好~ 不过话说回来,再怎么的精挑细选,java那边还是基本没有悬念,真正有悬念的,我们都心知肚明,呵呵。

所以真正运动之前先来点热身运动,看看哪个循环在我这相对要快:

require 'benchmark'

n = ARGV.empty? ? 10 ** 6 : 10 ** ARGV[0].to_i
puts "n=#{n}"
Benchmark.bmbm do |b|
  b.report("for:")    { for i in 1..n  ; a = "0"; end }
  b.report("times:")  { n.times do     ; a = "0"; end }
  b.report("upto:")   { 1.upto(n) do   ; a = "0"; end }
  b.report("downto:") { n.downto(1) do ; a = "0"; end }
end

以上是我所想到的比较常见的4种茴字写法,程序默认取n=10^6进行循环,也可以接受一个作为幂指数的命令行参数,Benchmark的bmbm方法会先dry run一遍所有test作为rehearsal,等memory和garbage collection的状态相对stable了以后才进行真正的benchmark,这样先运行和后运行的report会相对公平一点。

默认运行( n=10^6 )的结果如下:

n=1000000
Rehearsal -------------------------------------------
for:      0.310000   0.000000   0.310000 (  0.313392)
times:    0.290000   0.000000   0.290000 (  0.297268)
upto:     0.300000   0.000000   0.300000 (  0.300311)
downto:   0.310000   0.000000   0.310000 (  0.304146)
---------------------------------- total: 1.210000sec

              user     system      total        real
for:      0.310000   0.000000   0.310000 (  0.313129)
times:    0.290000   0.000000   0.290000 (  0.297470)
upto:     0.300000   0.000000   0.300000 (  0.302154)
downto:   0.310000   0.000000   0.310000 (  0.305562)

一次完整运行( n=10~10^8 )的数据结果如下:

n=10
Rehearsal -------------------------------------------
for:      0.000000   0.000000   0.000000 (  0.000018)
times:    0.000000   0.000000   0.000000 (  0.000011)
upto:     0.000000   0.000000   0.000000 (  0.000047)
downto:   0.000000   0.000000   0.000000 (  0.000053)
---------------------------------- total: 0.000000sec

              user     system      total        real
for:      0.000000   0.000000   0.000000 (  0.000014)
times:    0.000000   0.000000   0.000000 (  0.000011)
upto:     0.000000   0.000000   0.000000 (  0.000011)
downto:   0.000000   0.000000   0.000000 (  0.000011)
=====================================================

n=100
Rehearsal -------------------------------------------
for:      0.000000   0.000000   0.000000 (  0.000041)
times:    0.000000   0.000000   0.000000 (  0.000031)
upto:     0.000000   0.000000   0.000000 (  0.000033)
downto:   0.000000   0.000000   0.000000 (  0.000040)
---------------------------------- total: 0.000000sec

              user     system      total        real
for:      0.000000   0.000000   0.000000 (  0.000035)
times:    0.000000   0.000000   0.000000 (  0.000030)
upto:     0.000000   0.000000   0.000000 (  0.000031)
downto:   0.000000   0.000000   0.000000 (  0.000031)
=====================================================

n=1000
Rehearsal -------------------------------------------
for:      0.000000   0.000000   0.000000 (  0.000367)
times:    0.000000   0.000000   0.000000 (  0.000315)
upto:     0.000000   0.000000   0.000000 (  0.000319)
downto:   0.000000   0.000000   0.000000 (  0.000854)
---------------------------------- total: 0.000000sec

              user     system      total        real
for:      0.000000   0.000000   0.000000 (  0.000273)
times:    0.000000   0.000000   0.000000 (  0.000250)
upto:     0.000000   0.000000   0.000000 (  0.000254)
downto:   0.000000   0.000000   0.000000 (  0.000258)
=====================================================

n=10000
Rehearsal -------------------------------------------
for:      0.000000   0.000000   0.000000 (  0.003388)
times:    0.010000   0.000000   0.010000 (  0.003056)
upto:     0.000000   0.000000   0.000000 (  0.003006)
downto:   0.000000   0.000000   0.000000 (  0.003084)
---------------------------------- total: 0.010000sec

              user     system      total        real
for:      0.010000   0.000000   0.010000 (  0.003114)
times:    0.000000   0.000000   0.000000 (  0.002955)
upto:     0.000000   0.000000   0.000000 (  0.003047)
downto:   0.010000   0.000000   0.010000 (  0.004650)
=====================================================

n=100000
Rehearsal -------------------------------------------
for:      0.030000   0.000000   0.030000 (  0.032892)
times:    0.030000   0.000000   0.030000 (  0.029808)
upto:     0.030000   0.000000   0.030000 (  0.031190)
downto:   0.030000   0.000000   0.030000 (  0.030379)
---------------------------------- total: 0.120000sec

              user     system      total        real
for:      0.030000   0.000000   0.030000 (  0.033382)
times:    0.030000   0.000000   0.030000 (  0.029139)
upto:     0.030000   0.000000   0.030000 (  0.031608)
downto:   0.030000   0.000000   0.030000 (  0.030498)
=====================================================

n=1000000
Rehearsal -------------------------------------------
for:      0.310000   0.000000   0.310000 (  0.313392)
times:    0.290000   0.000000   0.290000 (  0.297268)
upto:     0.300000   0.000000   0.300000 (  0.300311)
downto:   0.310000   0.000000   0.310000 (  0.304146)
---------------------------------- total: 1.210000sec

              user     system      total        real
for:      0.310000   0.000000   0.310000 (  0.313129)
times:    0.290000   0.000000   0.290000 (  0.297470)
upto:     0.300000   0.000000   0.300000 (  0.302154)
downto:   0.310000   0.000000   0.310000 (  0.305562)
=====================================================

n=10000000
Rehearsal -------------------------------------------
for:      3.090000   0.000000   3.090000 (  3.109693)
times:    2.940000   0.010000   2.950000 (  2.946662)
upto:     2.990000   0.010000   3.000000 (  3.003812)
downto:   3.010000   0.000000   3.010000 (  3.021900)
--------------------------------- total: 12.050000sec

              user     system      total        real
for:      3.110000   0.010000   3.120000 (  3.119928)
times:    2.950000   0.010000   2.960000 (  2.992141)
upto:     3.000000   0.010000   3.010000 (  3.044853)
downto:   3.020000   0.000000   3.020000 (  3.036987)
=====================================================

n=100000000
Rehearsal -------------------------------------------
for:     30.950000   0.070000  31.020000 ( 31.139756)
times:   29.360000   0.060000  29.420000 ( 29.543839)
upto:    29.890000   0.070000  29.960000 ( 30.102346)
downto:  30.080000   0.070000  30.150000 ( 30.271642)
-------------------------------- total: 120.550000sec

              user     system      total        real
for:     31.130000   0.080000  31.210000 ( 31.359814)
times:   29.420000   0.050000  29.470000 ( 29.630556)
upto:    30.050000   0.060000  30.110000 ( 30.197589)
downto:  30.180000   0.050000  30.230000 ( 30.361343)
=====================================================

由于精力有限,就不做多次运行取平均值这种相对无聊的事情了,结果虽然不严谨也无法真正判断出究竟谁最快(times和upto,downto是在伯仲之间),但至少可以看出for in range是相对最慢的。

换ruby1.9后的运行结果与上基本一致,详细数据如下:

n=10
Rehearsal -------------------------------------------
for:      0.000000   0.000000   0.000000 (  0.000029)
times:    0.000000   0.000000   0.000000 (  0.000050)
upto:     0.000000   0.000000   0.000000 (  0.000014)
downto:   0.000000   0.000000   0.000000 (  0.000013)
---------------------------------- total: 0.000000sec

              user     system      total        real
for:      0.000000   0.000000   0.000000 (  0.000014)
times:    0.000000   0.000000   0.000000 (  0.000011)
upto:     0.000000   0.000000   0.000000 (  0.000012)
downto:   0.000000   0.000000   0.000000 (  0.000012)
=====================================================

n=100
Rehearsal -------------------------------------------
for:      0.000000   0.000000   0.000000 (  0.000061)
times:    0.000000   0.000000   0.000000 (  0.000103)
upto:     0.000000   0.000000   0.000000 (  0.000078)
downto:   0.000000   0.000000   0.000000 (  0.000060)
---------------------------------- total: 0.000000sec

              user     system      total        real
for:      0.000000   0.000000   0.000000 (  0.000066)
times:    0.000000   0.000000   0.000000 (  0.000061)
upto:     0.000000   0.000000   0.000000 (  0.000061)
downto:   0.000000   0.000000   0.000000 (  0.000061)
=====================================================

n=1000
Rehearsal -------------------------------------------
for:      0.000000   0.000000   0.000000 (  0.000465)
times:    0.000000   0.000000   0.000000 (  0.000461)
upto:     0.000000   0.000000   0.000000 (  0.000477)
downto:   0.000000   0.000000   0.000000 (  0.000428)
---------------------------------- total: 0.000000sec

              user     system      total        real
for:      0.000000   0.000000   0.000000 (  0.000388)
times:    0.000000   0.000000   0.000000 (  0.000339)
upto:     0.000000   0.000000   0.000000 (  0.000341)
downto:   0.000000   0.000000   0.000000 (  0.000339)
=====================================================

n=10000
Rehearsal -------------------------------------------
for:      0.000000   0.000000   0.000000 (  0.004486)
times:    0.010000   0.000000   0.010000 (  0.003675)
upto:     0.000000   0.000000   0.000000 (  0.004407)
downto:   0.000000   0.000000   0.000000 (  0.004121)
---------------------------------- total: 0.010000sec

              user     system      total        real
for:      0.010000   0.000000   0.010000 (  0.003961)
times:    0.000000   0.000000   0.000000 (  0.005113)
upto:     0.010000   0.000000   0.010000 (  0.003592)
downto:   0.000000   0.000000   0.000000 (  0.003592)
=====================================================

n=100000
Rehearsal -------------------------------------------
for:      0.040000   0.000000   0.040000 (  0.042573)
times:    0.030000   0.000000   0.030000 (  0.039094)
upto:     0.030000   0.000000   0.030000 (  0.041495)
downto:   0.040000   0.000000   0.040000 (  0.049316)
---------------------------------- total: 0.140000sec

              user     system      total        real
for:      0.040000   0.000000   0.040000 (  0.040422)
times:    0.040000   0.000000   0.040000 (  0.037030)
upto:     0.040000   0.000000   0.040000 (  0.041921)
downto:   0.040000   0.000000   0.040000 (  0.039868)
=====================================================

n=1000000
Rehearsal -------------------------------------------
for:      0.390000   0.000000   0.390000 (  0.401887)
times:    0.370000   0.000000   0.370000 (  0.376656)
upto:     0.370000   0.010000   0.380000 (  0.384750)
downto:   0.370000   0.000000   0.370000 (  0.380184)
---------------------------------- total: 1.510000sec

              user     system      total        real
for:      0.400000   0.000000   0.400000 (  0.411929)
times:    0.370000   0.000000   0.370000 (  0.386443)
upto:     0.370000   0.010000   0.380000 (  0.379820)
downto:   0.370000   0.000000   0.370000 (  0.379068)
=====================================================

n=10000000
Rehearsal -------------------------------------------
for:      3.920000   0.020000   3.940000 (  4.021434)
times:    3.690000   0.030000   3.720000 (  3.844118)
upto:     3.710000   0.030000   3.740000 (  3.844035)
downto:   3.700000   0.020000   3.720000 (  3.795330)
--------------------------------- total: 15.120000sec

              user     system      total        real
for:      3.910000   0.020000   3.930000 (  4.003016)
times:    3.670000   0.020000   3.690000 (  3.749495)
upto:     3.700000   0.020000   3.720000 (  3.919785)
downto:   3.690000   0.030000   3.720000 (  3.789975)
=====================================================

n=100000000
Rehearsal -------------------------------------------
for:     39.260000   0.240000  39.500000 ( 40.293460)
times:   36.700000   0.210000  36.910000 ( 37.450910)
upto:    37.020000   0.260000  37.280000 ( 38.963391)
downto:  36.940000   0.230000  37.170000 ( 37.806189)
-------------------------------- total: 150.860000sec

              user     system      total        real
for:     39.230000   0.240000  39.470000 ( 40.471694)
times:   36.850000   0.240000  37.090000 ( 38.302817)
upto:    36.870000   0.230000  37.100000 ( 37.802815)
downto:  36.970000   0.220000  37.190000 ( 38.052300)
=====================================================

有趣的是ruby1.9的循环操作性能竟然普遍都是负增长,这倒为我们之后的list performance比较埋下了伏笔。

热身运动到此结束,似乎有喧宾夺主之嫌,所以赶紧搞个part 2…,下篇文章我们会用上面循环性能测试的疑似最佳表现者times来进行list append性能测试,敬请期待。

历史上的今天:

Related posts:

Got something to say? Go for it!

使用新浪微博登陆