RSS
 

Archive for the ‘Ruby’ Category

Ruby 1.9.2 great performances

06 Sep

With a previous test, I found that JRuby was the highest expression in regard to the speed in executing ruby code, outperforming not only the C + + and .Net but also comparison with the last two incarnations of python. These are the scripts.

Now that Rails 3 is released and an interpreter suggested is the new 1.9.2, I was curious to observe how the official release works: well, I would say not bad!
This time I limited the number of participants alone versions installed with RVM and a couple more versions of Windows: JRuby 1.4.0 and the most used 1.8.7 mingw32, just to have a benchmark.

Linux distribution: Ubuntu 10.4 64bit
Windows XP 32Bit SP3

Version Builder/System Seconds
Ruby 1.9.2 p0 RVM x86_64-linux 6,6
JRuby 1.4.0 RVM OpenJDK 64-Bit Server VM 1.6.0_18 [amd64-java] 6,8
JRuby 1.5.2 RVM OpenJDK 64-Bit Server VM 1.6.0_18 [amd64-java] 7,0
JRuby 1.4.0 Windows Client VM 1.6.0_15 [x86-java] 7,0
Ruby 1.9.1 p378 RVM x86_64-linux 8,9
Ruby 1.8.7 p249 RVM x86_64-linux 12,2
Ruby 1.8.7 p249 i386-mingw32 23,9

This is the complete log of the execution:


marco@d9400:~$ rvm list

rvm rubies

=> jruby-1.4.0 [ amd64-java ]
jruby-1.5.2 [ amd64-java ]
ruby-1.8.7-p249 [ x86_64 ]
ruby-1.9.1-p378 [ x86_64 ]
ruby-1.9.2-p0 [ x86_64 ]

marco@d9400:~$ java -version
java version "1.6.0_18"
OpenJDK Runtime Environment (IcedTea6 1.8.1) (6b18-1.8.1-0ubuntu1)
OpenJDK 64-Bit Server VM (build 16.0-b13, mixed mode)

marco@d9400:~$ ruby -v
jruby 1.4.0 (ruby 1.8.7 patchlevel 174) (2009-11-02 69fbfa3) (OpenJDK 64-Bit Server VM 1.6.0_18) [amd64-java]
marco@d9400:~$ ruby RubyMM186_3.rb --server --fast

Warming up...
Strings test - Elapsed 2.096
Check1: 50000
Check2: 157490
Check3: 50005
Check4: 373847
Arrays test - Elapsed 3.508
Check1: 20900
Check2: 250000
Check3: 250000
Check4: 1500000
Check5: 5749950
Numeric test - Elapsed 2.856
Check1: 6252500
Check2: 1439295494700374021157505910939096377494040420940312
Ruby Partial elapsed time 8.460

1. Starting Ruby tests...
Strings test - Elapsed 1.501
Arrays test - Elapsed 3.054
Numeric test - Elapsed 2.280
Ruby Partial elapsed time 6.835

2. Starting Ruby tests...
Strings test - Elapsed 1.431
Arrays test - Elapsed 3.091
Numeric test - Elapsed 2.249
Ruby Partial elapsed time 6.771

3. Starting Ruby tests...
Strings test - Elapsed 1.505
Arrays test - Elapsed 2.999
Numeric test - Elapsed 2.261
Ruby Partial elapsed time 6.765
-------------------------------------
Average Strings test - Elapsed 1.479
Average Arrays test - Elapsed 3.048
Average Numeric test - Elapsed 2.263

Ruby Average elapsed time 6.790

marco@d9400:~$ rvm use jruby-1.5.2
marco@d9400:~$ ruby -v
jruby 1.5.2 (ruby 1.8.7 patchlevel 249) (2010-08-20 1c5e29d) (OpenJDK 64-Bit Server VM 1.6.0_18) [amd64-java]
marco@d9400:~$ ruby RubyMM186_3.rb --server --fast

Warming up...
Strings test - Elapsed 2.383
Check1: 50000
Check2: 157490
Check3: 50005
Check4: 373847
Arrays test - Elapsed 3.561
Check1: 20900
Check2: 250000
Check3: 250000
Check4: 1500000
Check5: 5749950
Numeric test - Elapsed 3.210
Check1: 6252500
Check2: 1439295494700374021157505910939096377494040420940312
Ruby Partial elapsed time 9.154

1. Starting Ruby tests...
Strings test - Elapsed 1.479
Arrays test - Elapsed 3.092
Numeric test - Elapsed 2.516
Ruby Partial elapsed time 7.087

2. Starting Ruby tests...
Strings test - Elapsed 1.431
Arrays test - Elapsed 3.056
Numeric test - Elapsed 2.508
Ruby Partial elapsed time 6.995

3. Starting Ruby tests...
Strings test - Elapsed 1.423
Arrays test - Elapsed 3.053
Numeric test - Elapsed 2.524
Ruby Partial elapsed time 7.000
-------------------------------------
Average Strings test - Elapsed 1.444
Average Arrays test - Elapsed 3.067
Average Numeric test - Elapsed 2.516

Ruby Average elapsed time 7.027

marco@d9400:~$ rvm use ruby-1.8.7-p249
marco@d9400:~$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]
marco@d9400:~$ ruby RubyMM186_3.rb

Warming up...
Strings test - Elapsed 3.135
Check1: 50000
Check2: 157490
Check3: 50005
Check4: 373847
Arrays test - Elapsed 4.386
Check1: 20900
Check2: 250000
Check3: 250000
Check4: 1500000
Check5: 5749950
Numeric test - Elapsed 4.629
Check1: 6252500
Check2: 1439295494700374021157505910939096377494040420940312
Ruby Partial elapsed time 12.149

1. Starting Ruby tests...
Strings test - Elapsed 3.181
Arrays test - Elapsed 4.402
Numeric test - Elapsed 4.598
Ruby Partial elapsed time 12.180

2. Starting Ruby tests...
Strings test - Elapsed 3.153
Arrays test - Elapsed 4.387
Numeric test - Elapsed 4.572
Ruby Partial elapsed time 12.113

3. Starting Ruby tests...
Strings test - Elapsed 3.210
Arrays test - Elapsed 4.395
Numeric test - Elapsed 4.583
Ruby Partial elapsed time 12.189
-------------------------------------
Average Strings test - Elapsed 3.181
Average Arrays test - Elapsed 4.395
Average Numeric test - Elapsed 4.584

Ruby Average elapsed time 12.160

marco@d9400:~$ rvm use ruby-1.9.1
marco@d9400:~$ ruby -v
ruby 1.9.1p378 (2010-01-10 revision 26273) [x86_64-linux]
marco@d9400:~$ ruby RubyMM191_3.rb

Warming up...
Strings test - Elapsed 2.452
Check1: 50000
Check2: 157490
Check3: 50005
Check4: 373847
Arrays test - Elapsed 4.488
Check1: 20900
Check2: 250000
Check3: 250000
Check4: 1500000
Check5: 5749950
Numeric test - Elapsed 1.840
Check1: 6252500
Check2: 1439295494700374021157505910939096377494040420940312
Ruby Partial elapsed time 8.780

1. Starting Ruby tests...
Strings test - Elapsed 2.314
Arrays test - Elapsed 4.679
Numeric test - Elapsed 1.843
Ruby Partial elapsed time 8.836

2. Starting Ruby tests...
Strings test - Elapsed 2.319
Arrays test - Elapsed 4.691
Numeric test - Elapsed 1.843
Ruby Partial elapsed time 8.853

3. Starting Ruby tests...
Strings test - Elapsed 2.318
Arrays test - Elapsed 4.705
Numeric test - Elapsed 1.847
Ruby Partial elapsed time 8.870
-------------------------------------
Average Strings test - Elapsed 2.317
Average Arrays test - Elapsed 4.692
Average Numeric test - Elapsed 1.844

Ruby Average elapsed time 8.853

marco@d9400:~$ rvm use ruby-1.9.2
marco@d9400:~$ ruby -v
ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-linux]
marco@d9400:~$ ruby RubyMM191_3.rb

Warming up...
Strings test - Elapsed 1.680
Check1: 50000
Check2: 157490
Check3: 50005
Check4: 373847
Arrays test - Elapsed 4.192
Check1: 20900
Check2: 250000
Check3: 250000
Check4: 1500000
Check5: 5749950
Numeric test - Elapsed 1.708
Check1: 6252500
Check2: 1439295494700374021157505910939096377494040420940312
Ruby Partial elapsed time 7.579

1. Starting Ruby tests...
Strings test - Elapsed 1.654
Arrays test - Elapsed 3.178
Numeric test - Elapsed 1.704
Ruby Partial elapsed time 6.536

2. Starting Ruby tests...
Strings test - Elapsed 1.746
Arrays test - Elapsed 3.388
Numeric test - Elapsed 1.699
Ruby Partial elapsed time 6.833

3. Starting Ruby tests...
Strings test - Elapsed 1.644
Arrays test - Elapsed 3.227
Numeric test - Elapsed 1.706
Ruby Partial elapsed time 6.577
-------------------------------------
Average Strings test - Elapsed 1.681
Average Arrays test - Elapsed 3.264
Average Numeric test - Elapsed 1.703

Ruby Average elapsed time 6.649

 
No Comments

Posted in JRuby, Ruby

 

Ruby vs Python vs Windows vs Linux

06 Mar

In the previous article, I examined the performance of some ruby and python interpreters on a Windows XP system. This time, I run the same script under Linux distribution: Ubuntu 9.10 2.6.31-20-generic. APT versions were installed via package manager, the RVM instead, through the Ruby Version Manager which build from sources.

Version Builder/System/VM Seconds
JRuby 1.4.0 APT Java HotSpot(TM) 64-Bit Server VM 1.6.0_16) [amd64-java] 6,1
JRuby 1.4.0 RVM Java HotSpot(TM) 64-Bit Server VM 1.6.0_16) [amd64-java] 6,2
Ruby 1.9.2 preview1 RVM x86_64-linux 6,5
JRuby 1.4.0 Windows Client VM 1.6.0_15 [x86-java] 6,9
Python 2.6.4 Windows 7,5
Ruby 1.9.1 p129 i386-mingw32 8,1
Python 2.6.4 APT x86_64-linux 8,7
Ruby 1.9.1 p378 RVM x86_64-linux 8,7
Ruby 1.9.1 p243 RVM x86_64-linux 8,8
Python 3.1.1 Windows 9,0
Ruby 1.9.1 p243 APT x86_64-linux 9,3
Ruby 1.9.1 p243 i386-mingw32 9,6
Ruby 1.8.7 p249 RVM x86_64-linux 12,2
IronRuby 0.9.3.0 Windows .NET 2.0.0.0 18,9
Ruby 1.9.1 p376 i386-mswin32 20,8
Ruby 1.8.7 p174 APT x86_64-linux 23,0
Ruby 1.8.6 p368 i386-mingw32 23,3
Ruby 1.8.7 p249 i386-mingw32 23,9
IronPython 2.6 Windows .NET 2.0.0.0 256,5
Jython 2.5.1 Windows Client VM 1.6.0_15 [x86-java] Timeout

Win vs Linux

Win vs Linux

 

Ruby vs Ruby vs Python vs Python

24 Jan

Another benchmark to compare some recent versions of ruby with the latest releases of Python. Two simple scripts to compare the syntax and performance of these modern languages.
The system on which I performed the test is a Dell Inspiron 9400 with Centrino Duo, Intel T7200 4Mb Cache, 2GHz, 2GB RAM 667Mhz. Windows XP Pro SP3.

This is the result of the first test, used to warming up for the VM:

Version Builder Seconds
Python 2.6.4 7,5
Ruby 1.9.1 p129 i386-mingw32 8,2
JRuby 1.4.0 Client VM 1.6.0_15 [x86-java] 9,0
Python 3.1.1 9,1
Ruby 1.9.1 p243 i386-mingw32 9,6
IronRuby 0.9.3.0 .NET 2.0.0.0 20,3
Ruby 1.9.1 p376 i386-mswin32 20,9
Ruby 1.8.6 p368 i386-mingw32 22,9
IronPython 2.6 .NET 2.0.0.0 225,4
Jython 2.5.1 Client VM 1.6.0_15 [x86-java] Timeout

Benchmark without warm up

Benchmark without warm up

The result below instead, refers to the average of three readings after the warm up. JRuby’s performance improves by 23%:

Version Builder Seconds
JRuby 1.4.0 Client VM 1.6.0_15 [x86-java] 6,9
Python 2.6.4 7,5
Ruby 1.9.1 p129 i386-mingw32 8,2
Python 3.1.1 9,0
Ruby 1.9.1 p243 i386-mingw32 10,0
IronRuby 0.9.3.0 .NET 2.0.0.0 18,9
Ruby 1.9.1 p376 i386-mswin32 20,6
Ruby 1.8.6 p368 i386-mingw32 23,2
IronPython 2.6 .NET 2.0.0.0 256,5
Jython 2.5.1 Client VM 1.6.0_15 [x86-java] Timeout

Benchmark after warm up

Benchmark after warm up

And here is the scripts. I tried to optimize every versions and to do that, I had to create two variations for each language.

Ruby 1.8.6:

def strings_test(ntest)
  r1 = r2 = r3 = 0
  xstr = ""
  ntest.times do 
    #Create a string, add 'abcde1234_' until getting a str size 1000
    xstr = 'abcde1234_' * 10000
 
    #Make letters upcase 
    xstr.upcase!
 
    #Change '1234_' with '67890 ' (space at last position)
    #Now the repeated string should be 'ABCDE67890 '
    xstr.gsub! '1234_', '67890 '
 
    #Cast numbers from 29 upto size/2 to string and add it to xstr variable, ciclying for every number (not add all numbers one time)
    29.upto(xstr.size/2) {|n| xstr << n.to_s}
 
    #Check 1: Count 'A' char 
    #Check 2: Count '9' char 
    0.upto(xstr.size-1) do |n| 
      if xstr[n].chr() == 'A'
        r1+=1 
      elsif xstr[n].chr() == '9'
        r2+=1
      end
    end
 
    #Create an array from xstr using space to split
    r3 += xstr.split.size
 
  end
 
  return r1, r2, r3, xstr
end
 
def arrays_test(ntest, xstr)
  r1 = r2 = r3 = r4 = r5 = 0
  ntest.times do 
    #Clear ar then add 5000 times this element: "I", "am", "great", null, "or", "number", 1
    ar =  []
    5000.times do
      ['I', 'am', 'great', nil, 'or', 'number', 1].each {|a| ar << a}
    end
 
    #...then reverse elements to obtain this order: 1, "number", "or", null, "great", "am", "I"
    ar.reverse!
 
    #...then, count the element with value "great" using two separate cicle
    #the first starting from 31 until 2955 (bounty inclused)
    31.upto(2955) do |n|
      r1 += 1 if ar[n] == 'great'
    end
    #the second looping all the array elements
    ar.each {|n| r2+=1 if n == 'great'}
 
    #Loop inside and build a temporary string with index and value, without put it into a variable and only for elements <> null
    ar.each_index{|i| ar[i] ? "#{i} #{ar[i]}" : r3+=1 }
 
    #delete null value elements and take its size
    ar.compact!
    r4 += ar.size
 
    #then join elements with space and take its size
    r5 += ar.join(' ').size
 
  end
 
  return r1, r2, r3, r4, r5
end
 
def nums_test(ntest)
  r1 = r2 = 0
 
  ntest.times do 
    #Find all prime numbers from 8 to 95 step by 3 and sum all primes got, to check the result
    #51.upto(307) do |n| 
    (8..95).step(3) do |n|
      primes(n).each {|a| r1 += a}
    end
 
    #Calculate factorial numbers start from 2 to 42
    r2 = 0
    for n in 2..42
      r2 += fac(n)
    end
  end
 
  return r1, r2
end
 
#Primes must return an array of prime numbers
def primes(n)
  ar = []
  for x in (2..n)
    prime = true
    for y in (2..x-1)
      if x%y == 0
        prime = false
        break
      end
    end
    ar << x if prime
  end
  return ar
end
 
def fac(n) (1..n).inject{|total, current| total * current} end
 
# ---  START  ---
puts "\nWarming up..."
t1=t2=t3=0
time = Time.now
r1, r2, r3, xstr = strings_test(5)
puts "Strings test - Elapsed %.3f" % (p1=Time.now - time)
puts "Check1: #{r1}"
puts "Check2: #{r2}"
puts "Check3: #{r3}"
puts "Check4: #{xstr.size}"
 
time = Time.now
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
puts "Arrays test  - Elapsed %.3f" % (p2=Time.now - time)
puts "Check1: #{r1}"
puts "Check2: #{r2}"
puts "Check3: #{r3}"
puts "Check4: #{r4}"
puts "Check5: #{r5}"
 
time = Time.now
r1, r2 = nums_test(500)
puts "Numeric test - Elapsed %.3f" % (p3=Time.now - time)
puts "Check1: #{r1}"
puts "Check2: #{r2}"
 
puts "Ruby Partial elapsed time %.3f" % (p1+p2+p3)
 
puts "\n1. Starting Ruby tests..."
 
time = Time.now
r1, r2, r3, xstr = strings_test(5)
puts "Strings test - Elapsed %.3f" % (p1=Time.now - time)
 
time = Time.now
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
puts "Arrays test  - Elapsed %.3f" % (p2=Time.now - time)
 
time = Time.now
r1, r2 = nums_test(500)
puts "Numeric test - Elapsed %.3f" % (p3=Time.now - time)
 
puts "Ruby Partial elapsed time %.3f" % (p1+p2+p3)
t1+=p1;t2+=p2;t3+=p3
 
puts "\n2. Starting Ruby tests..."
 
time = Time.now
r1, r2, r3, xstr = strings_test(5)
puts "Strings test - Elapsed %.3f" % (p1=Time.now - time)
 
time = Time.now
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
puts "Arrays test  - Elapsed %.3f" % (p2=Time.now - time)
 
time = Time.now
r1, r2 = nums_test(500)
puts "Numeric test - Elapsed %.3f" % (p3=Time.now - time)
 
puts "Ruby Partial elapsed time %.3f" % (p1+p2+p3)
t1+=p1;t2+=p2;t3+=p3
 
puts "\n3. Starting Ruby tests..."
 
time = Time.now
r1, r2, r3, xstr = strings_test(5)
puts "Strings test - Elapsed %.3f" % (p1=Time.now - time)
 
time = Time.now
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
puts "Arrays test  - Elapsed %.3f" % (p2=Time.now - time)
 
time = Time.now
r1, r2 = nums_test(500)
puts "Numeric test - Elapsed %.3f" % (p3=Time.now - time)
 
puts "Ruby Partial elapsed time %.3f" % (p1+p2+p3)
t1+=p1;t2+=p2;t3+=p3
 
puts "-------------------------------------"
puts "Average Strings test - Elapsed %.3f" % (t1/3)
puts "Average Arrays test  - Elapsed %.3f" % (t2/3)
puts "Average Numeric test - Elapsed %.3f" % (t3/3)
puts "\nRuby Average elapsed time %.3f" % (t1/3+t2/3+t3/3)

Ruby 1.9.1:

def strings_test(ntest)
  r1 = r2 = r3 = 0
  xstr = ""
  ntest.times do 
    #Create a string, add 'abcde1234_' until getting a str size 1000
    xstr = 'abcde1234_' * 10000
 
    #Make letters upcase 
    xstr.upcase!
 
    #Change '1234_' with '67890 ' (space at last position)
    #Now the repeated string should be 'ABCDE67890 '
    xstr.gsub! '1234_', '67890 '
 
    #Cast numbers to string, from 29 up to size/2. Add it to xstr variable as well, ciclying for every number (not adding all numbers once)
    29.upto(xstr.size/2) {|n| xstr << n.to_s}
 
    #Check 1: Count 'A' char 
    #Check 2: Count '9' char 
    0.upto(xstr.size-1) do |n| 
      if xstr[n] == 'A'
        r1+=1 
      elsif xstr[n] == '9'
        r2+=1
      end
    end
 
    #Create an array from xstr using space to split, its size is the third check
    r3 += xstr.split.size
 
  end
 
  return r1, r2, r3, xstr
end
 
def arrays_test(ntest, xstr)
  r1 = r2 = r3 = r4 = r5 = 0
  ntest.times do 
    #Clear ar then add 5000 times this element: "I", "am", "great", null, "or", "number", 1
    ar =  []
    5000.times do
      ['I', 'am', 'great', nil, 'or', 'number', 1].each {|a| ar << a}
    end
 
    #...then reverse elements to obtain this order: 1, "number", "or", null, "great", "am", "I"
    ar.reverse!
 
    #...then, count the element with value "great" using two separate cicle
    #the first starting from 31 until 2955 (bounty inclused)
    31.upto(2955) do |n|
      r1 += 1 if ar[n] == 'great'
    end
    #the second looping all the array elements
    ar.each {|n| r2+=1 if n == 'great'}
 
    #Loop inside and build a temporary string with index and value, without put it into a variable and only for elements <> null
    ar.each_index{|i| ar[i] ? "#{i} #{ar[i]}" : r3+=1 }
 
    #delete null value elements and take its size
    ar.compact!
    r4 += ar.size
 
    #then join elements with space and take its size
    r5 += ar.join(' ').size
 
  end
 
  return r1, r2, r3, r4, r5
end
 
def nums_test(ntest)
  r1 = r2 = 0
 
  ntest.times do 
    #Find all prime numbers from 8 to 95 step by 3 (bounds included) and sum all primes got, to check the result
    #51.upto(307) do |n| 
    (8..95).step(3) do |n|
      primes(n).each {|a| r1 += a}
    end
 
    #Calculate factorial numbers start from 2 to 42
    r2 = 0
    for n in 2..42
      r2 += fac(n)
    end
  end
 
  return r1, r2
end
 
#Primes must return an array of prime numbers
def primes(n)
  ar = []
  for x in (2..n)
    prime = true
    for y in (2..x-1)
      if x%y == 0
        prime = false
        break
      end
    end
    ar << x if prime
  end
  return ar
end
 
def fac(n) (1..n).inject{|total, current| total * current} end
 
# ---  START  ---
puts "\nWarming up..."
t1=t2=t3=0
time = Time.now
r1, r2, r3, xstr = strings_test(5)
puts "Strings test - Elapsed %.3f" % (p1=Time.now - time)
puts "Check1: #{r1}"
puts "Check2: #{r2}"
puts "Check3: #{r3}"
puts "Check4: #{xstr.size}"
 
time = Time.now
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
puts "Arrays test  - Elapsed %.3f" % (p2=Time.now - time)
puts "Check1: #{r1}"
puts "Check2: #{r2}"
puts "Check3: #{r3}"
puts "Check4: #{r4}"
puts "Check5: #{r5}"
 
time = Time.now
r1, r2 = nums_test(500)
puts "Numeric test - Elapsed %.3f" % (p3=Time.now - time)
puts "Check1: #{r1}"
puts "Check2: #{r2}"
 
puts "Ruby Partial elapsed time %.3f" % (p1+p2+p3)
 
puts "\n1. Starting Ruby tests..."
 
time = Time.now
r1, r2, r3, xstr = strings_test(5)
puts "Strings test - Elapsed %.3f" % (p1=Time.now - time)
 
time = Time.now
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
puts "Arrays test  - Elapsed %.3f" % (p2=Time.now - time)
 
time = Time.now
r1, r2 = nums_test(500)
puts "Numeric test - Elapsed %.3f" % (p3=Time.now - time)
 
puts "Ruby Partial elapsed time %.3f" % (p1+p2+p3)
t1+=p1;t2+=p2;t3+=p3
 
puts "\n2. Starting Ruby tests..."
 
time = Time.now
r1, r2, r3, xstr = strings_test(5)
puts "Strings test - Elapsed %.3f" % (p1=Time.now - time)
 
time = Time.now
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
puts "Arrays test  - Elapsed %.3f" % (p2=Time.now - time)
 
time = Time.now
r1, r2 = nums_test(500)
puts "Numeric test - Elapsed %.3f" % (p3=Time.now - time)
 
puts "Ruby Partial elapsed time %.3f" % (p1+p2+p3)
t1+=p1;t2+=p2;t3+=p3
 
puts "\n3. Starting Ruby tests..."
 
time = Time.now
r1, r2, r3, xstr = strings_test(5)
puts "Strings test - Elapsed %.3f" % (p1=Time.now - time)
 
time = Time.now
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
puts "Arrays test  - Elapsed %.3f" % (p2=Time.now - time)
 
time = Time.now
r1, r2 = nums_test(500)
puts "Numeric test - Elapsed %.3f" % (p3=Time.now - time)
 
puts "Ruby Partial elapsed time %.3f" % (p1+p2+p3)
t1+=p1;t2+=p2;t3+=p3
 
puts "-------------------------------------"
puts "Average Strings test - Elapsed %.3f" % (t1/3)
puts "Average Arrays test  - Elapsed %.3f" % (t2/3)
puts "Average Numeric test - Elapsed %.3f" % (t3/3)
puts "\nRuby Average elapsed time %.3f" % (t1/3+t2/3+t3/3)

Python 2.6:

from time import time
#import psyco
#psyco.full()
#psyco.full(memory=100)
#psyco.profile(0.05, memory=100)
#psyco.profile(0.2)
 
 
def strings_test(ntest):
  r1 = r2 = r3 = 0
  xstr = ""
  for x in xrange(ntest):
    #Create a string, add 'abcde1234_' until getting a xstr size 1000
    xstr = 'abcde1234_' * 10000
 
    #Make letters upcase 
    xstr = xstr.upper()
 
    #Change '1234_' with '67890 ' (space at last position)
    #Now the repeated string should be 'ABCDE67890 '
    xstr = xstr.replace('1234_', '67890 ')
 
    #Cast numbers to string, from 29 up to size/2. Add it to xstr variable as well, ciclying for every number (not adding all numbers once)
    for y in xrange(29,int(len(xstr)/2) + 1):
        xstr += "%s" %y
 
    #Result 1: Count 'A' char 
    #Result 2: Count '9' char 
    for y in xrange(0, len(xstr)):
      if xstr[y] == 'A':
        r1+=1 
      elif xstr[y] == '9':
        r2+=1
 
    #Create an array from xstr using space to split
    r3 += len(xstr.split())
 
 
  return r1, r2, r3, xstr
 
#Slower than other version
def multiremove(ar, what):
  i = 0
  for el in ar:
    if el == what:
      del ar[i]
    i+=1
 
#Ugly but a bit faster
def multiremove2(ar, what):
  todel = [] 
  for y in xrange(0,len(ar)):
    if ar[y] == what:
       todel.append(y)
  todel.reverse()
  for y in todel:
     ar.pop(y)
 
def arrays_test(ntest, xstr):
  r1 = r2 = r3 = r4 = r5 = 0
  for x in xrange(ntest):
    #Clear ar then add 5000 times this element: "I", "am", "great", null, "or", "number", 1
    ar = []
    for y in xrange(0, 5000):
      ar.extend(["I", "am", "great", None, "or", "number", 1])
 
    #...then reverse elements to obtain this order: 1, "number", "or", null, "great", "am", "I"
    ar.reverse()
 
    #...then, count the element with value "great" using two separate cicle
    #the first starting from 31 until 2955 (bounty included)
    for y in xrange(31,2955):
      if ar[y] == "great": r1 +=1
 
    #the second looping all the array elements
    for y in xrange(0, len(ar)):
      if ar[y] == "great": r2+=1
 
    #Loop inside and build a temporary string with index and value, without put it into a variable and only for elements <> null
    for y in xrange(0, len(ar)):
      if ar[y]:
        "%s %s" %(y, ar[y])
      else:
        r3+=1
 
    #delete null value elements and take its size
    multiremove2(ar, None)
    r4 += len(ar)
 
    #then join elements with space and take its size
    r5 += len(" ".join(str(n) for n in ar))
 
  return r1, r2, r3, r4, r5
 
def nums_test(ntest):
  r1 = r2 = 0
  for x in xrange(ntest):
    #Find all prime numbers from 8 to 95 step by 3 (bounds included) and sum all primes got, to check the result
    for n in xrange(8, 96, 3):
      for prime in primes(n):
        r1 += prime
    fac = lambda n:[1,0][n>0] or fac(n-1)*n
    #Calculate factorial numbers start from 2 to 42 (bounds included)
    r2 = 0
    for n in xrange(2, 43):
      r2 += fac(n)
 
  return r1, r2
 
#Primes must return an array of prime numbers
def primes(n):
  ar = []
  for x in xrange(2, n+1):
    prime = True
    for y in xrange(2, x):
      if x%y == 0:
        prime = False
        break
    if prime:
      ar.append(x)
  return ar
 
# ---  START  ---
print "\nWarming up..."
t1=t2=t3=0
stime = time()
r1, r2, r3, xstr = strings_test(5)
p1=time() - stime
print "Strings test - Elapsed %.3f" % (p1)
print "Check1: %s" %r1
print "Check2: %s" %r2
print "Check3: %s" %r3
print "Check4: %d" %(len(xstr))
 
stime = time()
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
p2=time() - stime
print  "Arrays test - Elapsed %.3f" % (p2)
print "Check1: %s" %r1
print "Check2: %s" %r2
print "Check3: %s" %r3
print "Check4: %s" %r4
print "Check5: %s" %r5
 
stime = time()
r1, r2 = nums_test(500)
p3=time() - stime
print "Numeric test  - Elapsed %.3f" % (p3)
print "Check1: %s" %r1
print "Check2: %s" %r2
 
print  "Python Partial elapsed time %.3f" % (p1+p2+p3)
 
print "\n1. Starting Python tests..."
 
stime = time()
r1, r2, r3, xstr = strings_test(5)
p1=time() - stime
print "Strings test - Elapsed %.3f" % (p1)
 
stime = time()
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
p2=time() - stime
print  "Arrays test  - Elapsed %.3f" % (p2)
 
stime = time()
r1, r2 = nums_test(500)
p3=time() - stime
print "Numeric test - Elapsed %.3f" % (p3)
 
print  "Python Partial elapsed time %.3f" % (p1+p2+p3)
t1+=p1;t2+=p2;t3+=p3
 
print "\n2. Starting Python tests..."
 
stime = time()
r1, r2, r3, xstr = strings_test(5)
p1=time() - stime
print "Strings test - Elapsed %.3f" % (p1)
 
stime = time()
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
p2=time() - stime
print  "Arrays test  - Elapsed %.3f" % (p2)
 
stime = time()
r1, r2 = nums_test(500)
p3=time() - stime
print "Numeric test - Elapsed %.3f" % (p3)
 
print  "Python Partial elapsed time %.3f" % (p1+p2+p3)
t1+=p1;t2+=p2;t3+=p3
 
print "\n3. Starting Python tests..."
 
stime = time()
r1, r2, r3, xstr = strings_test(5)
p1=time() - stime
print "Strings test - Elapsed %.3f" % (p1)
 
stime = time()
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
p2=time() - stime
print  "Arrays test  - Elapsed %.3f" % (p2)
 
stime = time()
r1, r2 = nums_test(500)
p3=time() - stime
print "Numeric test - Elapsed %.3f" % (p3)
 
print  "Python Partial elapsed time %.3f" % (p1+p2+p3)
t1+=p1;t2+=p2;t3+=p3
 
print "-------------------------------------"
print "Average Strings test - Elapsed %.3f" % (t1/3)
print "Average Arrays test  - Elapsed %.3f" % (t2/3)
print "Average Numeric test - Elapsed %.3f" % (t3/3)
print "Python Average elapsed time %.3f" % (t1/3+t2/3+t3/3)

Python 3.1:

from time import time
#import psyco
#psyco.full()
#psyco.full(memory=100)
#psyco.profile(0.05, memory=100)
#psyco.profile(0.2)
 
 
def strings_test(ntest):
  r1 = r2 = r3 = 0
  xstr = ""
  for x in range(ntest):
    #Create a string, add 'abcde1234_' until getting a xstr size 1000
    xstr = 'abcde1234_' * 10000
 
    #Make letters upcase 
    xstr = xstr.upper()
 
    #Change '1234_' with '67890 ' (space at last position)
    #Now the repeated string should be 'ABCDE67890 '
    xstr = xstr.replace('1234_', '67890 ')
 
    #Cast numbers from 29 upto 1028 to string and add it to xstr variable, ciclying for every number (not add all numbers one time)
    for y in range(29,int(len(xstr)/2) + 1):
        xstr += "%s" %y
 
    #Result 1: Count 'A' char 
    #Result 2: Count '9' char 
    for y in range(0, len(xstr)):
      if xstr[y] == 'A':
        r1+=1 
      elif xstr[y] == '9':
        r2+=1
 
    #Create an array from xstr using space to split
    r3 += len(xstr.split())
 
 
  return r1, r2, r3, xstr
 
#Slower than other version
def multiremove(ar, what):
  i = 0
  for el in ar:
    if el == what:
      del ar[i]
    i+=1
 
#Ugly but a bit faster
def multiremove2(ar, what):
  todel = [] 
  for y in range(0,len(ar)):
    if ar[y] == what:
       todel.append(y)
  todel.reverse()
  for y in todel:
     ar.pop(y)
 
def arrays_test(ntest, xstr):
  r1 = r2 = r3 = r4 = r5 = 0
  for x in range(ntest):
    #Clear ar then add 5000 times this element: "I", "am", "great", null, "or", "number", 1
    ar = []
    for y in range(0, 5000):
      ar.extend(["I", "am", "great", None, "or", "number", 1])
 
    #...then reverse elements to obtain this order: 1, "number", "or", null, "great", "am", "I"
    ar.reverse()
 
    #...then, count the element with value "great" using two separate cicle
    #the first starting from 31 until 2955 (bounty included)
    for y in range(31,2955):
      if ar[y] == "great": r1 +=1
 
    #the second looping all the array elements
    for y in range(0, len(ar)):
      if ar[y] == "great": r2+=1
 
    #Loop inside and build a temporary string with index and value, without put it into a variable and only for elements <> null
    for y in range(0, len(ar)):
      if ar[y]:
        "%s %s" %(y, ar[y])
      else:
        r3+=1
 
    #delete null value elements and take its size
    multiremove2(ar, None)
    r4 += len(ar)
 
    #then join elements with space and take its size
    r5 += len(" ".join(str(n) for n in ar))
 
  return r1, r2, r3, r4, r5
 
def nums_test(ntest):
  r1 = r2 = 0
  for x in range(ntest):
    #Find all prime numbers from 8 to 95 step by 3 (bounds included) and sum all primes got, to check the result
    for n in range(8, 96, 3):
      for prime in primes(n):
        r1 += prime
    fac = lambda n:[1,0][n>0] or fac(n-1)*n
    #Calculate factorial numbers start from 2 to 42 (bounds included)
    r2 = 0
    for n in range(2, 43):
      r2 += fac(n)
 
  return r1, r2
 
#Primes must return an array of prime numbers
def primes(n):
  ar = []
  for x in range(2, n+1):
    prime = True
    for y in range(2, x):
      if x%y == 0:
        prime = False
        break
    if prime:
      ar.append(x)
  return ar
 
# ---  START  ---
print("\nWarming up...")
t1=t2=t3=0
stime = time()
r1, r2, r3, xstr = strings_test(5)
p1=time() - stime
print("Strings test - Elapsed %.3f" % p1)
print("Check1: %s" % r1)
print("Check2: %s" % r2)
print("Check3: %s" % r3)
print("Check4: %d" % len(xstr))
 
stime = time()
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
p2=time() - stime
print("Arrays test - Elapsed %.3f" % p2)
print("Check1: %s" % r1)
print("Check2: %s" % r2)
print("Check3: %s" % r3)
print("Check4: %s" % r4)
print("Check5: %s" % r5)
 
stime = time()
r1, r2 = nums_test(500)
p3=time() - stime
print("Numeric test - Elapsed %.3f" % p3)
print("Check1: %s" % r1)
print("Check2: %s" % r2)
 
print( "Python Partial elapsed time %.3f" % (p1+p2+p3))
 
print("\n1. Starting Python tests...")
 
stime = time()
r1, r2, r3, xstr = strings_test(5)
p1=time() - stime
print("Strings test - Elapsed %.3f" % p1)
 
stime = time()
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
p2=time() - stime
print( "Arrays test  - Elapsed %.3f" % p2)
 
stime = time()
r1, r2 = nums_test(500)
p3=time() - stime
print("Numeric test - Elapsed %.3f" % p3)
 
print( "Python Partial elapsed time %.3f" % (p1+p2+p3))
t1+=p1;t2+=p2;t3+=p3
 
print("\n2. Starting Python tests...")
 
stime = time()
r1, r2, r3, xstr = strings_test(5)
p1=time() - stime
print("Strings test - Elapsed %.3f" % p1)
 
stime = time()
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
p2=time() - stime
print( "Arrays test  - Elapsed %.3f" % p2)
 
stime = time()
r1, r2 = nums_test(500)
p3=time() - stime
print("Numeric test - Elapsed %.3f" % p3)
 
print( "Python Partial elapsed time %.3f" % (p1+p2+p3))
t1+=p1;t2+=p2;t3+=p3
 
print("\n3. Starting Python tests...")
 
stime = time()
r1, r2, r3, xstr = strings_test(5)
p1=time() - stime
print("Strings test - Elapsed %.3f" % p1)
 
stime = time()
r1, r2, r3, r4, r5 = arrays_test(50, xstr)
p2=time() - stime
print( "Arrays test  - Elapsed %.3f" % p2)
 
stime = time()
r1, r2 = nums_test(500)
p3=time() - stime
print("Numeric test - Elapsed %.3f" % p3)
 
print( "Python Partial elapsed time %.3f" % (p1+p2+p3))
t1+=p1;t2+=p2;t3+=p3
 
print("-------------------------------------")
print("Average Strings test - Elapsed %.3f" % (t1/3))
print("Average Arrays test  - Elapsed %.3f" % (t2/3))
print("Average Numeric test - Elapsed %.3f" % (t3/3))
print("Python Average elapsed time %.3f" % (t1/3+t2/3+t3/3))
 

Comparison script languages for the fractal geometry

24 Aug

This article will compare the latest incarnations of Ruby, with the latest in Python, Groovy, PHP, Lua, Perl and Java too, to have a comparison with a pre-compiled language. We will see, how scripting languages behave if applied to fractal geometry, more precisely an family Mandelbrot algorithm.
Browsing on the net, I found a comparison very interesting but a bit dated, dates back more than two years ago. Since then things have changed and I took advantage to make an update, not including all of those languages but only for more known. This is an opportunity to compare Ruby and Python versions even in their Java and. NET, an intention that I had since long time.

Using a fractal as a convenient benchmark plus: if an attempt to optimize not be successful if it has been the evidence and being drawn in real time, you can feel the speed. The fractal is drawn in ASCII also because the use of external libraries would have drugged the outcome.

                                       *
                                       *
                                       *
                                       *
                                       *
                                      ***
                                     *****
                                     *****
                                      ***
                                       *
                                   *********
                                 *************
                                ***************
                             *********************
                             *********************
                              *******************
                              *******************
                              *******************
                              *******************
                            ***********************
                              *******************
                              *******************
                             *********************
                              *******************
                              *******************
                               *****************
                                ***************
                                 *************
                                   *********
                                       *
                                ***************
                            ***********************
                         * ************************* *
                         *****************************
                      * ******************************* *
                       *********************************
                      ***********************************
                    ***************************************
               *** ***************************************** ***
               *************************************************
                ***********************************************
                 *********************************************
                 *********************************************
                ***********************************************
                ***********************************************
              ***************************************************
               *************************************************
               *************************************************
              ***************************************************
              ***************************************************
         *    ***************************************************    *
       *****  ***************************************************  *****
       ****** *************************************************** ******
      ******* *************************************************** *******
    ***********************************************************************
    ********* *************************************************** *********
       ****** *************************************************** ******
       *****  ***************************************************  *****
              ***************************************************
              ***************************************************
              ***************************************************
              ***************************************************
               *************************************************
               *************************************************
              ***************************************************
                ***********************************************
                ***********************************************
                  *******************************************
                   *****************************************
                 *********************************************
                **** ****************** ****************** ****
                 ***  ****************   ****************  ***
                  *    **************     **************    *
                         ***********       ***********
                         **  *****           *****  **
                          *   *                 *   *

This is the system for the test:
Dell Inspiron 9400, Centrino Duo, T7200 @ 2Ghz 4Mb Cache L1, Ram 2Gb @ 667Mhz
Windows XP pro SP3
Java 6 update 15
Microsoft .NET 3.5 SP1

These are the performance results obtained from an average of five runs, took after have executed some void attempts (I have not trusted the VM startup):

Language      Time (in seconds)  n times slower tha java
_____________________________________________________________
Java 6 update 15    0,153
Lua 5.1.4           0,815	           5x
Php 5.3.0           2,083	          14x
Python 2.6.2        2,269 	          15x
Python 3.1.1        1,566 	          10x
Jython 2.5.0        2,850 	          19x
Jruby 1.3.1         2,466 	          16x
Groovy 1.6.3        6,491 	          42x
Ruby 1.9.1 p129	    2,688 	          18x
Ruby 1.8.6 p368	    6,863 	          45x
Ruby 1.8.6 p111	    9,709 	          63x
IronRuby 0.9.0	    6,038 	          39x
IronPyhon 2.0.2     0,978 	           6x
Perl 5.10.0         2,722 	          18x

This is the chart, of course lower values indicate better performance

Chart

These are the scripts used to generate the fractal, the originals was good, I have only done a few simple changes to run Python 3.1 or slightly improve the already excellent readability in Ruby and Lua.

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// by Erik Wrenholt
import java.util.*;
 
class Bench1
{  
	static int BAILOUT = 16;
	static int MAX_ITERATIONS = 1000;
 
	private static int iterate(float x, float y)
	{
		float cr = y-0.5f;
		float ci = x;
		float zi = 0.0f;
		float zr = 0.0f;
		int i = 0;
		while (true) {
			i++;
			float temp = zr * zi;
			float zr2 = zr * zr;
			float zi2 = zi * zi;
			zr = zr2 - zi2 + cr;
			zi = temp + temp + ci;
			if (zi2 + zr2 > BAILOUT)
				return i;
			if (i > MAX_ITERATIONS)
				return 0;
		}
	}
 
	public static void main(String args[])
	{
		Date d1 = new Date();
		int x,y;
		for (y = -39; y < 39; y++) {
			System.out.print("n");
			for (x = -39; x < 39; x++) {
				if (iterate(x/40.0f,y/40.0f) == 0) 
					System.out.print("*");
				else
					System.out.print(" ");
 
			}
		}
		Date d2 = new Date();
		long diff = d2.getTime() - d1.getTime();
		System.out.println("nJava Elapsed " + diff/1000.0f);
 
	}
}

Lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
-- By Erik Wrenholt
 
local BAILOUT = 16
local MAX_ITERATIONS = 1000
 
function iterate(x,y)
 
  local cr = y-0.5
  local ci = x
  local zi = 0.0
  local zr = 0.0
  local i = 0
 
  while 1 do
    i = i+1
    local temp = zr * zi
    local zr2 = zr*zr
    local zi2 = zi*zi
    zr = zr2-zi2+cr
    zi = temp+temp+ci
    if (zi2+zr2 > BAILOUT) then
      return i
    end
    if (i > MAX_ITERATIONS) then
      return 0
    end
  end
end
 
function bench1()
  local t = os.clock()
  for y = -39, 38 do
    for x = -39, 38 do
    if (iterate(x/40.0, y/40) == 0) then io.write("*") else io.write(" ") end
    end
    io.write("n")
  end
  io.write(string.format("Time Elapsed %.3fn", os.clock() - t))
end
 
bench1()

Php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?php
define("BAILOUT",16);
define("MAX_ITERATIONS",1000);
 
class Bench1
{
 
	function Bench1()
	{
		$d1 = microtime(1);
		for ($y = -39; $y < 39; $y++) {
			echo("n");
			for ($x = -39; $x < 39; $x++) {
				if ($this->iterate($x/40.0,$y/40.0) == 0) 
					echo("*");
				else
					echo(" ");
			}
		}
		$d2 = microtime(1);
		$diff = $d2 - $d1;
		printf("nPHP Elapsed %0.3f", $diff);
	}
 
	function iterate($x,$y)
	{
		$cr = $y-0.5;
		$ci = $x;
		$zi = 0.0;
		$zr = 0.0;
		$i = 0;
		while (true) {
			$i++;
			$temp = $zr * $zi;
			$zr2 = $zr * $zr;
			$zi2 = $zi * $zi;
			$zr = $zr2 - $zi2 + $cr;
			$zi = $temp + $temp + $ci;
			if ($zi2 + $zr2 > BAILOUT)
				return $i;
			if ($i > MAX_ITERATIONS)
				return 0;
		}
	}
}
 
new Bench1();
?>

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import sys, time
stdout = sys.stdout
 
BAILOUT = 16
MAX_ITERATIONS = 1000
 
class Bench1:
  def __init__(self):
    print ('Rendering...')
    for y in range(-39, 39):
      stdout.write('n')
      for x in range(-39, 39):
        i = self.start(x/40.0, y/40.0)
 
        if i == 0:
          stdout.write('*')
        else:
          stdout.write(' ')
 
  def start(self, x, y):
    cr = y - 0.5
    ci = x
    zi = zr = 0.0
    i = 0
 
    while True:
      i += 1
      temp = zr * zi
      zr2 = zr * zr
      zi2 = zi * zi
      zr = zr2 - zi2 + cr
      zi = temp + temp + ci
 
      if zi2 + zr2 > BAILOUT:
        return i
      if i > MAX_ITERATIONS:
        return 0
 
t = time.time()
Bench1()
print ('nPython Elapsed %.3f' % (time.time() - t))

Groovy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//Created By Marco Mastrodonato 22/09/2009
 
class Bench1{
    public int BAILOUT = 16
    public int MAX_ITERATIONS = 1000
 
    def Bench1(){
        println("Rendering...")
        for (y in -39..39){
            println("")
            for (x in -39..39){
                if (iterate(x/40.0, y/40.0) == 0){
                    print("*")
                } else {
                    print(" ")
                }
            }
        }
    }
 
    def iterate(x,y){
        float cr = y-0.5
        float ci = x
        float zi = 0.0
        float zr = 0.0
        def i = 0
        while(1){
            i += 1
            float temp = zr * zi
            float zr2 = zr * zr
            float zi2 = zi * zi
            zr = zr2 - zi2 + cr
            zi = temp + temp + ci
            if (zi2 + zr2 > BAILOUT){ 
                return i
            }
            if (i > MAX_ITERATIONS){ 
                return 0
            } 
        }
    }
 
}
 
time1 = new Date().time
new Bench1()
time2 = new Date().time
float elapsed = (time2 - time1)/1000
println("nGroovy Elapsed ${elapsed}")

Ruby

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
BAILOUT = 16
MAX_ITERATIONS = 1000
 
class Bench1
 
  def initialize
    puts "Rendering..."
    for y in -39..39
      print "n"
      for x in -39..39
        i = iterate x/40.0, y/40.0
        if i == 0 then print "*" else print " " end
      end
    end
  end
 
  def iterate(x,y)
    cr = y-0.5
    ci = x
    zi = zr = 0.0
    i = 0
    while true
      i += 1
      temp = zr * zi
      zr2 = zr * zr
      zi2 = zi * zi
      zr = zr2 - zi2 + cr
      zi = temp + temp + ci
      return i if zi2 + zr2 > BAILOUT
      return 0 if i > MAX_ITERATIONS
    end
  end
end
 
time = Time.now
Bench1.new
puts "nRuby Elapsed %.3f" % (Time.now - time)

Perl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# Ported from C to Perl by Anders Bergh <anders1@gmail.com>
 
$BAILOUT=16;
$MAX_ITERATIONS=1000;
 
$begin = time();
 
sub mandelbrot {
       local $x = $_[0];
       local $y = $_[1];
 
       local $cr = $y - 0.5;
       local $ci = $x;
       local $zi = 0.0;
       local $zr = 0.0;
       local $i = 0;
 
       while (1)
       {
               $i = $i + 1;
               local $temp = $zr * $zi;
               local $zr2 = $zr * $zr;
               local $zi2 = $zi * $zi;
               $zr = $zr2 - $zi2 + $cr;
               $zi = $temp + $temp + $ci;
               if ($zi2 + $zr2 > $BAILOUT)
               {
                       return $i;
               }
               if ($i > $MAX_ITERATIONS)
               {
                       return 0;
               }
       }
}
 
for ($y = -39; $y < 39; $y++)
{
       print("n");
       for ($x = -39; $x < 39; $x++)
       {
               $i = mandelbrot($x/40.0, $y/40.0);
               if ($i == 0)
               {
                       print("*");
               }
               else
               {
                       print(" ");
               }
       }
}
print("n");
 
$end = time() - $begin;
 
printf ("Perl Elapsed %.3fn",$end);

Comments:

The speed of Lua isn’t a news: only 5 times slower than compiled Java code, the best result. Its simplicity is its strength, maybe that’s what makes it so fast? It was adopted by Blizzard in the videogame “World of Warcraft” and if they did so, with no doubt, there is a reason. It is not object-oriented, does not natively support objects even if there is a project LOOP that extends this programming model.
PHP and Perl does not need comments.
Among the C version of Ruby and Python is clearly faster the second. The fair comparison would be the Rb1.8.6 with Py2.6.2 and Rb1.9.1 with Py3.1.1.
The challenge between the versions that uses the Java VM: Groovy, Jython and JRuby, sees the last as the winner. Groovy is far behind as performance in this test but the biggest question I have is: who is it for? As syntax is not bad but, imho, Ruby is even more fluent and then have that rake that is so convenient for many things.
The challenge between the .NET versions sees IronPython incredibly forward! But what they put in, the dynamite? It will be very interesting to examine the new ASP.NET MVC framework recently arrived at version 1 and that will be included in the framework. Net 4, there are projects for both IronRuby IronPython.
If this article was interesting, perhaps you can find something else through the advertisements of my sponsor, is in the right column, thanks!
Bye!

 

Five rubies in the multicore challenge

24 Aug

The system on which I performed the test is a laptop: Dell Inspiron 9400 with Centrino Duo, Intel T7200 4MB Cache 2GHz (166×12) 2GB Ram 667Mhz. This is a physical system Windows XP Pro SP3.

The purpose: to check the exploitation of more processor cores (two in my case) by comparing a single process with a double execution simultaneously.

To do this I used the string’s bench used in a previous article .
It must be remembered that the implementation of the dual process, everyone must share the CPU with the operating system (the load is always 100%) while in the single test that does not happen, a core is dedicated only to the test. For this reason, the operating system didn’t run antivirus or other heavy processes.

Let’s start with the oldest interpreter:

Ruby 1.8.6 patch 111

C:LavoroProgettiTestBench>ruby -v
ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-mswin32]

C:LavoroProgettiTestBench>ruby bench_str.rb
                           user     system      total        real
Concat 1.000.000:
+                      6.641000   0.000000   6.641000 (  6.640000)
<<                     5.344000   0.000000   5.344000 (  5.375000)
#{}                    6.078000   0.000000   6.078000 (  6.078000)
Add 100.000:
+=                     3.547000   2.969000   6.516000 (  6.579000)
<<                     0.062000   0.000000   0.062000 (  0.062000)
a = a + '.'            3.000000   3.422000   6.422000 (  6.547000)
#{}                    4.531000   1.906000   6.437000 (  6.516000)
Other 100.000:
* 100:                 0.500000   0.063000   0.563000 (  0.562000)
capitalize:            1.719000   0.078000   1.797000 (  1.797000)
upcase:                4.906000   0.140000   5.046000 (  5.047000)
chomp:                 0.266000   0.063000   0.329000 (  0.328000)
include:               1.234000   0.000000   1.234000 (  1.234000)
index:                 1.235000   0.000000   1.235000 (  1.250000)
sub:                   0.875000   0.094000   0.969000 (  0.969000)
gsub:                 17.453000   0.562000  18.015000 ( 18.047000)
[x..y]:                0.547000   0.016000   0.563000 (  0.562000)
slice:                 0.562000   0.000000   0.562000 (  0.563000)
strip:                 0.156000   0.000000   0.156000 (  0.156000)
Each:                 12.282000   0.078000  12.360000 ( 12.390000)
Cast 1.000.000:
.to_i:                 0.437000   0.000000   0.437000 (  0.438000)
.to_sym:               0.531000   0.000000   0.531000 (  0.531000)
split:                 9.047000   0.140000   9.187000 (  9.235000)
--- Total:            80.953000   9.531000  90.484000 ( 90.906000)
Ruby 1.8.6 patch 111

Ruby 1.8.6 patch 111

Single thread:

--- Total:            80.953000   9.531000  90.484000 ( 90.906000)

Double simultaneous execution:

CORE1:
--- Total:            87.063000  19.531000 106.594000 (107.923000)

CORE2:
--- Total:            91.344000  18.375000 109.719000 (110.125000)

This is the decrease of the double simultaneous execution:
Decrease by 10%
Real decrease of 20%

Ruby 1.8.6 patch 368

C:LavoroProgettiTestBench>ruby -v
ruby 1.8.6 (2009-03-31 patchlevel 368) [i386-mingw32]

C:LavoroProgettiTestBench>ruby bench_str.rb
                           user     system      total        real
Concat 1.000.000:
+                      4.828000   0.000000   4.828000 (  4.828125)
<<                     3.938000   0.000000   3.938000 (  3.953125)
#{}                    4.719000   0.016000   4.735000 (  4.750000)
Add 100.000:
+=                     3.687000   2.719000   6.406000 (  6.468750)
<<                     0.047000   0.000000   0.047000 (  0.046875)
a = a + '.'            3.422000   3.000000   6.422000 (  6.468750)
#{}                    4.797000   1.109000   5.906000 (  5.906250)
Other 100.000:
* 100:                 0.328000   0.094000   0.422000 (  0.421875)
capitalize:            0.890000   0.078000   0.968000 (  1.000000)
upcase:                3.469000   0.109000   3.578000 (  3.578125)
chomp:                 0.235000   0.078000   0.313000 (  0.312500)
include:               0.796000   0.000000   0.796000 (  0.796875)
index:                 0.797000   0.000000   0.797000 (  0.796875)
sub:                   0.750000   0.172000   0.922000 (  0.921875)
gsub:                 20.860000   0.531000  21.391000 ( 21.421875)
[x..y]:                0.437000   0.016000   0.453000 (  0.453125)
slice:                 0.438000   0.000000   0.438000 (  0.437500)
strip:                 0.109000   0.000000   0.109000 (  0.109375)
Each:                  9.078000   0.172000   9.250000 (  9.281250)
Cast 1.000.000:
.to_i:                 0.297000   0.000000   0.297000 (  0.296875)
.to_sym:               0.344000   0.000000   0.344000 (  0.343750)
split:                 7.375000   0.109000   7.484000 (  7.500000)
--- Total:            71.641000   8.203000  79.844000 ( 80.093750)
Ruby 1.8.6 patch 368

Ruby 1.8.6 patch 368

Single thread:

--- Total:            71.641000   8.203000  79.844000 ( 80.093750)

Double simultaneous execution:

CORE1:
--- Total:            80.797000  17.750000  98.547000 ( 99.093750)
CORE2:
--- Total:            76.500000  19.375000  95.875000 ( 97.187500)

Decrease of 9,8%
Real decrease of 22,5%

Ruby 1.9.1

C:LavoroProgettiTestBench>ruby -v
ruby 1.9.1p129 (2009-05-12 revision 23412) [i386-mingw32]

C:LavoroProgettiTestBench>ruby bench_str.rb
                           user     system      total        real
Concat 1.000.000:
+                      2.610000   0.000000   2.610000 (  2.609375)
<<                     2.125000   0.000000   2.125000 (  2.125000)
#{}                    2.796000   0.000000   2.796000 (  2.796875)
Add 100.000:
+=                     3.688000   2.875000   6.563000 (  6.609375)
<<                     0.031000   0.000000   0.031000 (  0.031250)
a = a + '.'            3.235000   3.265000   6.500000 (  6.578125)
#{}                    5.187000   2.266000   7.453000 (  7.546875)
Other 100.000:
* 100:                 0.203000   0.125000   0.328000 (  0.328125)
capitalize:            5.563000   0.047000   5.610000 (  5.656250)
upcase:                0.703000   0.031000   0.734000 (  0.734375)
chomp:                 0.219000   0.063000   0.282000 (  0.296875)
include:               0.156000   0.000000   0.156000 (  0.156250)
index:                 0.156000   0.000000   0.156000 (  0.156250)
sub:                   0.500000   0.093000   0.593000 (  0.593750)
gsub:                  8.453000   0.266000   8.719000 (  8.718750)
[x..y]:                0.219000   0.000000   0.219000 (  0.218750)
slice:                 0.219000   0.000000   0.219000 (  0.218750)
strip:                 0.109000   0.000000   0.109000 (  0.109375)
Each:                  7.188000   0.141000   7.329000 (  7.328125)
Cast 1.000.000:
.to_i:                 0.234000   0.000000   0.234000 (  0.234375)
.to_sym:               0.391000   0.000000   0.391000 (  0.390625)
split:                 4.609000   0.000000   4.609000 (  4.609375)
--- Total:            48.594000   9.172000  57.766000 ( 58.046875)
Ruby 1.9.1 patch 129

Ruby 1.9.1 patch 129

Single thread:

--- Total:            48.594000   9.172000  57.766000 ( 58.046875)

Double simultaneous execution:

CORE1:
--- Total:            56.345000  19.219000  75.564000 ( 76.312500)
CORE2:
--- Total:            52.109000  20.703000  72.812000 ( 74.156250)

Decrease of 11,5%
Real decrease of 29,6%

jRuby 1.3.1

C:LavoroProgettiTestBench>jruby -v
jruby 1.3.1 (ruby 1.8.6p287) (2009-07-24 6586) (Java HotSpot(TM) Client VM 1.6.0
_15) [x86-java]

C:LavoroProgettiTestBench>jruby bench_str.rb
                           user     system      total        real
Concat 1.000.000:
+                      1.703000   0.000000   1.703000 (  1.672000)
<<                     1.375000   0.000000   1.375000 (  1.375000)
#{}                    0.625000   0.000000   0.625000 (  0.625000)
Add 100.000:
+=                     8.343000   0.000000   8.343000 (  8.343000)
<<                     0.031000   0.000000   0.031000 (  0.031000)
a = a + '.'            8.406000   0.000000   8.406000 (  8.406000)
#{}                   18.984000   0.000000  18.984000 ( 18.984000)
Other 100.000:
* 100:                 0.157000   0.000000   0.157000 (  0.157000)
capitalize:            0.937000   0.000000   0.937000 (  0.937000)
upcase:                1.703000   0.000000   1.703000 (  1.703000)
chomp:                 0.063000   0.000000   0.063000 (  0.063000)
include:               0.281000   0.000000   0.281000 (  0.281000)
index:                 0.313000   0.000000   0.313000 (  0.313000)
sub:                   0.437000   0.000000   0.437000 (  0.437000)
gsub:                  4.813000   0.000000   4.813000 (  4.813000)
[x..y]:                0.156000   0.000000   0.156000 (  0.156000)
slice:                 0.140000   0.000000   0.140000 (  0.140000)
strip:                 0.047000   0.000000   0.047000 (  0.047000)
Each:                  3.094000   0.000000   3.094000 (  3.094000)
Cast 1.000.000:
.to_i:                 0.609000   0.000000   0.609000 (  0.609000)
.to_sym:               0.266000   0.000000   0.266000 (  0.266000)
split:                 2.203000   0.000000   2.203000 (  2.203000)
--- Total:            54.686000   0.000000  54.686000 ( 54.655000)
jRuby 1.3.1 => 1.8.6 p287

jRuby 1.3.1 => 1.8.6 p287

Single thread:

--- Total:            54.686000   0.000000  54.686000 ( 54.655000)

Double simultaneous execution:

CORE1:
--- Total:            65.170000   0.000000  65.170000 ( 64.920000)
CORE2:
--- Total:            64.234000   0.000000  64.234000 ( 64.000000)

Decrease of 17,2%
Real decrease of 17,9%

IronRuby 0.9.0

C:LavoroProgettiTestBench>ir -v
IronRuby 0.9.0.0 on .NET 2.0.0.0

C:LavoroProgettiTestBench>ir bench_str.rb
                           user     system      total        real
Concat 1.000.000:
+                      3.562500   0.000000   3.562500 (  3.234375)
<<                     1.531250   0.000000   1.531250 (  1.531250)
#{}                    1.453125   0.015625   1.468750 (  1.453125)
Add 100.000:
+=                    54.656250  11.296875  65.953125 ( 66.171875)
<<                     0.031250   0.000000   0.031250 (  0.031250)
a = a + '.'           54.734375  11.718750  66.453125 ( 66.671875)
#{}                   55.609375  10.843750  66.453125 ( 66.609375)
Other 100.000:
* 100:                 0.671875   0.000000   0.671875 (  0.671875)
capitalize:            2.593750   0.000000   2.593750 (  2.609375)
upcase:                7.484375   0.000000   7.484375 (  7.500000)
chomp:                 0.250000   0.000000   0.250000 (  0.250000)
include:               5.968750   0.015625   5.984375 (  6.031250)
index:                 5.968750   0.031250   6.000000 (  6.031250)
sub:                   1.781250   0.015625   1.796875 (  1.781250)
gsub:                 12.203125   0.031250  12.234375 ( 12.281250)
[x..y]:                0.406250   0.000000   0.406250 (  0.390625)
slice:                 0.343750   0.000000   0.343750 (  0.343750)
strip:                 0.078125   0.000000   0.078125 (  0.078125)
Each:                 31.546875   0.312500  31.859375 ( 32.203125)
Cast 1.000.000:
.to_i:                 0.265625   0.000000   0.265625 (  0.250000)
.to_sym:               0.406250   0.015625   0.421875 (  0.421875)
split:                 5.515625   0.031250   5.546875 (  5.531250)
--- Total:           247.062500  34.328125 281.390625 (282.078125)

C:LavoroProgettiTestBench>
IronRuby 0.9.0

IronRuby 0.9.0

Single thread:

--- Total:           247.062500  34.328125 281.390625 (282.078125)

Double simultaneous execution:

CORE1:
--- Total:           315.531250  40.578125 356.109375 (359.500000)
CORE2:
--- Total:           300.484375  46.156250 346.640625 (350.265625)

Decrease of 24,5%
Real decrease of 25,8%

Summary

Ruby 1.8.6 patch 111
Decrease of 10%
Real decrease of 20%

Ruby 1.8.6 patch 368
Decrease of 9,8%
Real decrease of 22,5%

Ruby 1.9.1
Decrease of 11,5%
Real decrease of 29,6%

jRuby 1.3.1
Decrease of 17,2%
Real decrease of 17,9%

IronRuby 0.9.0
Decrease of 24,5%
Real decrease of 25,8%

Conclusions

In this test, JRuby is the only one that has a uniform load on both cores and it does almost constantly for all the time. Only at the end moves towards a core but with more discretion. Also good performance with the two processes simultaneously.

Versions 1.8.6 and 1.9.1 are quite aligned and able to share the load solely on test "Add". The performance of the dual process would not be bad but creates problems for the system (at least mine) which prolongs the time.

IronRuby has some trouble with the strings already highlighted in a previous article. Ignoring this issue, the second core was left unloaded for all the duration. With the second core free, I would have expected a less pronounced decrease in the test process twice but it did not happen, this is strange.

In a future article, I'd like to repeat the test on a server quad core.

 
Comments Off

Posted in IronRuby .NET, JRuby, Ruby

 

FreeTTS, a java library used from jRuby on Rails

23 Aug

In this article we will see how to use the Java classes contained in a JAR file.
For this purpose we use a nice open source library developed by Carnegie Mellon University: FreeTTS.
The acronym TTS means Text To speech, makes it possible to transform a text into audio format. We’ll use it in a jRuby on Rails’s project to make us read the text we enter in the db.

In a previous article, we have seen how to configure the environment, so let’s start creating the new application:


C:>rails ProvaFreeTTS

In the lib folder from the root, create a sub folder freetts. Download the file freetts-1.2.2freetts-1.2.2-bin.zip, unpack the contents to a temporary folder, copy only the contents of the folder lib (jar files and JSAPI) into the dir just created: your_applibfreetts.

Now we create the jar’s interface to the jar:

#libfreetts.rb
 
require 'freetts/freetts.jar'
 
import com.sun.speech.freetts.Voice
import com.sun.speech.freetts.VoiceManager
import com.sun.speech.freetts.util.Utilities
 
class FreeTTS
  def initialize
    @voice = VoiceManager.getInstance.getVoice(Utilities.getProperty("voice16kName","kevin16"))
    @voice.allocate
  end
 
  def speak(txt=nil)
    return nil unless txt
    @voice.speak txt
  end
end

Let’s create a simple resource “sentence” with a single field “body“.


C:ProvaFreeTTS>jruby script/generate scaffold sentence body:text

Now we create two new operations, as I explained in detail in a previous article.

We start from the controller by adding at the bottom :

  #appcontrollerssentences_controller.rb
 
  def speak
    @sentence = Sentence.new(params[:sentence])
    require 'freetts'
    tts = FreeTTS.new
    tts.speak @sentence.body
    render (@sentence.new_record? ? :new : :edit)
  end
 
  def read
    @sentence = Sentence.find(params[:id])
    require 'freetts'
    tts = FreeTTS.new
    tts.speak @sentence.body
    redirect_to :back
  end

Now it’s the views turn.

We create a new partial where we’ll move into the resource’s data form, so to have only one form for every operation:

#appviewssentence_sentence.html.erb
 
<% form_for(@sentence) do |f| %>
  <%= f.error_messages %>
 
  <p>
    <%= f.label :body %><br />
    <%= f.text_area :body %>
  </p>
  <p>
    <%= f.submit 'Update' %>
  </p>
<% end %>
 
<h2>Preview</h2>
<% form_for @sentence, :url => speak_sentences_path, :method => :put do |f| %>
  <%= f.error_messages %>
 
  <p>
    <%= f.label :body %><br />
    <%= f.text_area :body %>
  </p>
  <p>
    <%= f.submit 'Speak' %>
  </p>
<% end %>

Add a clone of the form created by the scaffold but with a different action, to call the transaction speak.

Now modify the views created automatically:

#appviewssentencenew.html.erb
 
<h1>New sentence</h1>
 
<%= render @sentence %>
 
<%= link_to 'Back', sentences_path %>
 
#appviewssentenceedit.html.erb
 
<h1>Editing sentence</h1>
 
<%= render @sentence %>
 
<%= link_to 'Show', @sentence %> |
<%= link_to 'Back', sentences_path %>

Now, we modify the index in order to retrieve the second operation: the “read”. Basically, clicking on the corresponding line, will read the text previously stored in the db.

We only need to add a line to obtain this view:

#appviewssentenceindex.html.erb
<h1>Listing sentences</h1>
 
<table>
  <tr>
    <th>Body</th>
  </tr>
 
<% @sentences.each do |sentence| %>
  <tr>
    <td><%=h sentence.body %></td>
    <td><%= link_to 'Read', read_sentence_path(sentence) %></td>
    <td><%= link_to 'Show', sentence %></td>
    <td><%= link_to 'Edit', edit_sentence_path(sentence) %></td>
    <td><%= link_to 'Destroy', sentence, :confirm => 'Are you sure?', :method => :delete %></td>
  </tr>
<% end %>
</table>
 
<br />
 
<%= link_to 'New sentence', new_sentence_path %>

We modify the routing:

#configroutes.rb
 
#change map.resources :sentences with
map.resources :sentences, :member => { :read => :get }, :collection => { :speak => :put }
 
#add
map.root :controller => "sentences"

Configure the database.yml file, we create the db and tables with rake and start up Glassfish as explained in this previous article (find database.yml).

As we have seen, using java libraries with jruby on rails is very simple, we are ready to make our server to say the most dirty words!

The project can be downloaded from here.

Enjoy!

 
Comments Off

Posted in JRuby, Ruby on Rails

 

Setting up an environment for jRuby on Rails

20 Aug

My apologize in advance for having used a robot translator, a small help to save a little time:

Over the next few articles i will use jruby 1.3.1 with Rails 2.3.3 and this is an opportunity to write two lines about how to configure the system.
By the way, the system used is a virtualized windows xp, java sdk 6, Glassfish as application server and javadb.

Download and install the java sdk, at the moment we are at version 6 update 14.

There is also the sdk with NetBeans, an excellent IDE to manage projects ruby on rails. It could be an opportunity to try it. The package also includes the application server Glassfish V3.

Now we download and install jRuby, atm we are at version 1.3.1.

Installation is simple: unpack the zip in a path like C:rubyjruby-131

Let’s set the environment variables, right click on “My Computer” icon on the desktop -> Properties -> select the tab “Advanced” -> click on “environment variables”.

  • Add to the PATH variable the path to the bin folder where we installed jruby, for example C:rubyjruby-131bin.
  • Set the environment variable JAVA_HOME. In the “system variables” -> “New” -> as the name “JAVA_HOME” value as the installation path dell’sdk for example C:ProgrammiJavajdk1.6.0_14

It is not necessary to restart the operating system, we test the result:

C:>jruby -v
jruby 1.3.1 (ruby 1.8.6p287) (2009-06-15 2fd6c3d) (Java HotSpot(TM) Client VM 1.6.0_14) [x86-java]

Eureka! Now we’re ready to use jruby, jirb and gem. If in your system there is also classic ruby you may specify jruby-S to recall gem otherwise you can also put jruby path in the last position inside environment variable. Ok, now we can install rails 2.3.3:

C:>jruby -S gem install rails
Successfully installed activesupport-2.3.3
Successfully installed activerecord-2.3.3
Successfully installed actionpack-2.3.3
Successfully installed actionmailer-2.3.3
Successfully installed activeresource-2.3.3
Successfully installed rails-2.3.3
6 gems installed
Installing ri documentation for activesupport-2.3.3...
Installing ri documentation for activerecord-2.3.3...
Installing ri documentation for actionpack-2.3.3...
Installing ri documentation for actionmailer-2.3.3...
Installing ri documentation for activeresource-2.3.3...
Installing ri documentation for rails-2.3.3...
Installing RDoc documentation for activesupport-2.3.3...
Installing RDoc documentation for activerecord-2.3.3...
Installing RDoc documentation for actionpack-2.3.3...
Installing RDoc documentation for actionmailer-2.3.3...
Installing RDoc documentation for activeresource-2.3.3...
Installing RDoc documentation for rails-2.3.3...

We install the jdbc adapter to connect to Java DB (i don’t use jruby-S anymore, in my system is not necessary):

C:>gem install activerecord-jdbcderby-adapter
Successfully installed activerecord-jdbc-adapter-0.9.1
Successfully installed jdbc-derby-10.4.2.0
Successfully installed activerecord-jdbcderby-adapter-0.9.1
3 gems installed
Installing ri documentation for activerecord-jdbc-adapter-0.9.1...
Installing ri documentation for jdbc-derby-10.4.2.0...
Installing ri documentation for activerecord-jdbcderby-adapter-0.9.1...
Installing RDoc documentation for activerecord-jdbc-adapter-0.9.1...
Installing RDoc documentation for jdbc-derby-10.4.2.0...
Installing RDoc documentation for activerecord-jdbcderby-adapter-0.9.1...

Then install the gem for Glassfish:

C:>gem install glassfish
Successfully installed rack-1.0.0
Successfully installed glassfish-0.9.5-universal-java
2 gems installed
Installing ri documentation for rack-1.0.0...
Installing ri documentation for glassfish-0.9.5-universal-java...
Installing RDoc documentation for rack-1.0.0...
Installing RDoc documentation for glassfish-0.9.5-universal-java...

We are ready, we create a new project:

C:>rails ProvaArticolo

… in the database’s configuration file we use:

# config/database.yml
 
# JavaDB Setup
#
# You may need to copy derby.jar into
#  TODO: location C:rubyjruby-131lib
# With Java SE 6 and later this is not necessary.
development:
  adapter: derby
  database: db/development.db
 
# Warning: The database defined as 'test' will be erased and
# re-generated from your development database when you run 'rake'.
# Do not set this db to the same as development or production.
test:
  adapter: derby
  database: db/test.db
 
# Warning: The database defined as 'test' will be erased and
# re-generated from your development database when you run 'rake'.
# Do not set this db to the same as development or production.
production:
  adapter: derby
  database: db/production.db
 
# Warning: The database defined as 'test' will be erased and
# re-generated from your development database when you run 'rake'.
# Do not set this db to the same as development or production.

Let us start the server, from the prompt inside our application’s directory:

C:ProvaArticolo>glassfish
Starting GlassFish server at: 127.0.0.1:3000 in development environment...
Writing log messages to: C:/ProvaArticolo/log/development.log.
Press Ctrl+C to stop.

At http://localhost:3000/ should see the welcome page.
Now stop the server with Ctrl + C db and create the environment in development:

C:ProvaArticolo>rake db:create
(in C:/ProvaArticolo)
db/development.db already exists

We create something within the database, we start with the source of rails:

C:ProvaArticolo>jruby script/generate scaffold article name:string body:text
create app/models/
exists app/controllers/
exists app/helpers/
exists app/views/articles
create app/views/layouts/
create test/functional/
create test/unit/
create test/unit/helpers/
create public/stylesheets/
create app/views/articles/index.html.erb
create app/views/articles/show.html.erb
create app/views/articles/new.html.erb
create app/views/articles/edit.html.erb
create app/views/layouts/articles.html.erb
create public/stylesheets/scaffold.css
create app/controllers/articles_controller.rb
create test/functional/articles_controller_test.rb
create app/helpers/articles_helper.rb
create test/unit/helpers/articles_helper_test.rb
route map.resources :articles
dependency model
exists app/models/
exists test/unit/
create test/fixtures/
create app/models/article.rb
create test/unit/article_test.rb
create test/fixtures/articles.yml
exists db/migrate
create db/migrate/20090729171105_create_articles.rb

and create the table:

C:ProvaArticolo>rake db:migrate
(in C:/ProvaArticolo)
== CreateArticles: migrating =================================================
-- create_table(:articles)
-> 0.0700s
-> 0 rows
== CreateArticles: migrated (0.0700s) ========================================

Finally remove the index.html file from inside the public folder and create the initial route:

#configroutes.rb
map.root :controller => "articles"

Reboot the server and at http://localhost:3000/ this time we should see a list of articles.

If I don’t have forgotten something, jruby on rails is ready, enjoy!

 
1 Comment

Posted in Ruby

 

Best practise with four ruby’s interpreters

20 Aug

It cannot be denied that versatility is one of its features, a true multi-platform. There are interpreters for many operating systems and in addition to the classic C version we have JRuby, a viable alternative for the java world and we also have Ironruby for the Microsoft’s .NET, arrived in recent days at a fairly mature version.
Not bad! Think about the benefits that a company may have: a language easy to learn but very powerful, has an excellent framework (one in all, Rails) to quickly develop applications for intranets and in addition to all this, the chance to use the java’s or .net’s libraries.

In this article we will read about these four interpreters:

  1. Ruby 1.8.6 patch 368 updated at 2009-03-31
  2. Ruby 1.9.1 patch 129 updated at 2009-05-12 revision 23412
  3. jRuby 1.3.1 (ruby 1.8.6p287) 2009-06-15 Client VM 1.6.0 update 14
  4. IronRuby 0.9.0.0 on .NET 2.0.0.0

The Purpose: To discover the main differences in performance of the individual interpreter. There are methods and techniques that lead to the same result, without such tests can be difficult to determine which is the best practice.
In tests that we will see, I have focused on the processing speed and only roughly the amount of memory used.

The system: The physical machine is a Windows XP Professional SP3 32bit with an Intel E7300 dual core with 3Mb of cache, and 3.25 Gb of ram.

physical machine

physical machine

The tests running on a virtualized system with MS Virtual PC 2007, Windows XP Pro, Java SDK 6:14,. NET Framework 3.5 SP1, single-core processor, 768MB memory. Only the heaviest test (hash) was repeated with 2Gb.

Benchmarks are divided into four categories:

  • Strings
  • Numbers
  • Array
  • Hash

These tests that I created, are limited to perform very simple operations. At the bottom there is a total, but should not be construed as an index to the actual interpreter’s performance because it changes a lot according to the tests selected and those that I used, is not said that are conditions encountered in actual use.

Strings

This is the first script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
require "benchmark"
include Benchmark
 
Benchmark.bm(21, "--- Total:") do|b|
  puts "Concat 1.000.000:"
  n=1_000_000
  t1 = b.report("+") do
    n.times { "a "+"b "+"c "+"d "+"e "; "f "+"g" }
  end
  t1 += b.report("<<") do
    n.times { "a "<<"b "<<"c "<<"d "<<"e "; "f "<<"g" }
  end
  t1 += b.report("#{}") do
    sa="a"; sb="b"; sc="c"; sd="d"; se="e"
    n.times { "#{sa} #{sb} #{sc} #{sd} #{se}"; "#{sb} #{sc}" }
  end
 
  puts "Add 100.000:"
  n=100_000
  t2 = b.report("+=") do
    a = ""
    n.times { a += "." }
  end
  t2 += b.report("<<") do
    a = ""
    n.times { a << "." }
  end
  t2 += b.report("a = a + '.'") do
    a = ""
    n.times { a = a + "." }
  end
  t2 += b.report("#{}") do
    a = ""
    n.times { a = "#{a}." }
  end
 
  puts "Other 100.000:"
  n=100_000
  str=""
  t3 = b.report("* 100:") do
    n.times { str = " abc def ghi rn" * 100 }
  end
  t3 += b.report("capitalize:") do
    n.times { str.capitalize }
  end
  t3 += b.report("upcase:") do
    n.times { str.upcase }
  end
  t3 += b.report("chomp:") do
    n.times { str.chomp }
  end
  t3 += b.report("include:") do
    n.times { str.include?("ghi");str.include?("qwertyuiopasdfghjkl") }
  end
  t3 += b.report("index:") do
    n.times { str.index("ghi");str.index("qwertyuiopasdfghjkl") }
  end
  t3 += b.report("sub:") do
    n.times { str.sub("ghi", "GGHHII") }
  end
  t3 += b.report("gsub:") do
    n.times { str.gsub("ghi", "GGHHII") }
  end
  t3 += b.report("[x..y]:") do
    n.times {|x| str[0..2];str[5..15];str[6..26];str[10..50] }
  end
  t3 += b.report("slice:") do
    n.times {|x| str.slice(0..2);str.slice(5..15);str.slice(6..26);str.slice(10..50) }
  end
  t3 += b.report("strip:") do
    n.times {|x| "  1 2 3 4 5  ".strip }
  end
  t3 += b.report("Each:") do
    n.times { str.each_line{|x| x } }
  end
 
  puts "Cast 1.000.000:"
  n=1_000_000
  str="abcd1234"
  t4 = b.report(".to_i:") do
    n.times { str.to_i }
  end
  t4 += b.report(".to_sym:") do
    n.times { str.to_sym }
  end
  n=100_000
  str="abc123 " * 100
  t4 += b.report("split:") do
    n.times { str.split }
  end
 
  [t1+t2+t3+t4]
end

These results are sorted by interpreter, from first to quarter:

Ruby 1.8.6

C:>ruby bench_str.rb
                           user     system      total        real
Concat 1.000.000:
+                      3.525000   0.000000   3.525000 (  3.555325)
<<                     2.864000   0.000000   2.864000 (  2.884320)
#{}                    3.565000   0.010000   3.575000 (  3.615415)
Add 100.000:
+=                     5.257000   4.306000   9.563000 (  9.724565)
<<                     0.030000   0.010000   0.040000 (  0.040060)
a = a + '.'            5.398000   4.376000   9.774000 (  9.884805)
#{}                    5.328000   2.474000   7.802000 (  7.901835)
Other 100.000:
* 100:                 0.551000   0.380000   0.931000 (  0.981470)
capitalize:            0.951000   0.361000   1.312000 (  1.311965)
upcase:                2.844000   0.490000   3.334000 (  3.365040)
chomp:                 0.491000   0.301000   0.792000 (  0.861290)
include:               0.631000   0.000000   0.631000 (  0.630945)
index:                 0.611000   0.000000   0.611000 (  0.610915)
sub:                   1.181000   0.410000   1.591000 (  1.602400)
gsub:                 19.989000   1.623000  21.612000 ( 21.842715)
[x..y]:                0.351000   0.000000   0.351000 (  0.360540)
slice:                 0.350000   0.000000   0.350000 (  0.350525)
strip:                 0.090000   0.000000   0.090000 (  0.090135)
Each:                  7.711000   0.000000   7.711000 (  7.761625)
Cast 1.000.000:
.to_i:                 0.221000   0.000000   0.221000 (  0.220330)
.to_sym:               0.240000   0.000000   0.240000 (  0.240360)
split:                 6.229000   0.010000   6.239000 (  6.269390)
--- Total:            68.408000  14.751000  83.159000 ( 84.105970)

Ruby 1.9.1

C:>ruby bench_str.rb
                           user     system      total        real
Concat 1.000.000:
+                      1.932000   0.000000   1.932000 (  1.992985)
<<                     1.633000   0.000000   1.633000 (  1.672505)
#{}                    2.183000   0.000000   2.183000 (  2.213315)
Add 100.000:
+=                     5.538000   4.136000   9.674000 (  9.884805)
<<                     0.030000   0.000000   0.030000 (  0.030045)
a = a + '.'            5.368000   4.346000   9.714000 (  9.884805)
#{}                    6.529000   4.246000  10.775000 ( 11.096620)
Other 100.000:
* 100:                 0.491000   0.400000   0.891000 (  0.891335)
capitalize:            4.406000   0.501000   4.907000 (  4.977455)
upcase:                0.671000   0.501000   1.172000 (  1.171755)
chomp:                 0.541000   0.340000   0.881000 (  0.911365)
include:               0.110000   0.000000   0.110000 (  0.110165)
index:                 0.120000   0.000000   0.120000 (  0.120180)
sub:                   0.731000   0.371000   1.102000 (  1.111665)
gsub:                  7.361000   0.991000   8.352000 (  8.512750)
[x..y]:                0.200000   0.010000   0.210000 (  0.210315)
slice:                 0.170000   0.000000   0.170000 (  0.170255)
strip:                 0.090000   0.000000   0.090000 (  0.090135)
Each:                  6.359000   0.020000   6.379000 (  6.419615)
Cast 1.000.000:
.to_i:                 0.171000   0.000000   0.171000 (  0.170255)
.to_sym:               0.290000   0.000000   0.290000 (  0.330495)
split:                 3.575000   0.000000   3.575000 (  3.595385)
--- Total:            48.499000  15.862000  64.361000 ( 65.568205)

JRuby

C:>jruby bench_str.rb
                           user     system      total        real
Concat 1.000.000:
+                      1.142000   0.000000   1.142000 (  1.101000)
<<                     0.932000   0.000000   0.932000 (  0.942000)
#{}                    0.430000   0.000000   0.430000 (  0.430000)
Add 100.000:
+=                     7.962000   0.000000   7.962000 (  7.962000)
<<                     0.020000   0.000000   0.020000 (  0.020000)
a = a + '.'            7.542000   0.000000   7.542000 (  7.542000)
#{}                   16.324000   0.000000  16.324000 ( 16.324000)
Other 100.000:
* 100:                 0.140000   0.000000   0.140000 (  0.140000)
capitalize:            0.781000   0.000000   0.781000 (  0.781000)
upcase:                1.382000   0.000000   1.382000 (  1.382000)
chomp:                 0.051000   0.000000   0.051000 (  0.051000)
include:               0.240000   0.000000   0.240000 (  0.240000)
index:                 0.230000   0.000000   0.230000 (  0.230000)
sub:                   0.381000   0.000000   0.381000 (  0.391000)
gsub:                  3.816000   0.000000   3.816000 (  3.816000)
[x..y]:                0.100000   0.000000   0.100000 (  0.100000)
slice:                 0.120000   0.000000   0.120000 (  0.120000)
strip:                 0.040000   0.000000   0.040000 (  0.040000)
Each:                  2.333000   0.000000   2.333000 (  2.333000)
Cast 1.000.000:
.to_i:                 0.470000   0.000000   0.470000 (  0.470000)
.to_sym:               0.191000   0.000000   0.191000 (  0.191000)
split:                 1.622000   0.000000   1.622000 (  1.622000)
--- Total:            46.249000   0.000000  46.249000 ( 46.227999)

IronRuby

C:>ir bench_str.rb
                           user     system      total        real
Concat 1.000.000:
+                      2.804032   0.070101   2.874133 (  2.954425)
<<                     1.101584   0.000000   1.101584 (  1.101650)
#{}                    1.331915   0.000000   1.331915 (  1.342010)
Add 100.000:
+=                    50.502619   4.836955  55.339574 ( 56.043940)
<<                     0.040058   0.000000   0.040058 (  0.040060)
a = a + '.'           50.662850   4.616638  55.279488 ( 56.013895)
#{}                   51.173584   4.666710  55.840294 ( 56.634825)
Other 100.000:
* 100:                 0.500720   0.000000   0.500720 (  0.500750)
capitalize:            2.503600   0.010014   2.513614 (  2.583870)
upcase:                6.078741   0.000000   6.078741 (  6.199285)
chomp:                 0.200288   0.000000   0.200288 (  0.200300)
include:               4.216062   0.000000   4.216062 (  4.246360)
index:                 4.135947   0.000000   4.135947 (  4.206300)
sub:                   1.462102   0.000000   1.462102 (  1.492235)
gsub:                  8.692499   0.020029   8.712528 (  8.773140)
[x..y]:                0.290418   0.000000   0.290418 (  0.290435)
slice:                 0.230331   0.010014   0.240346 (  0.260390)
strip:                 0.070101   0.000000   0.070101 (  0.070105)
Each:                 25.015971   0.050072  25.066043 ( 25.357980)
Cast 1.000.000:
.to_i:                 0.220317   0.000000   0.220317 (  0.220330)
.to_sym:               0.280403   0.000000   0.280403 (  0.280420)
split:                 4.446394   0.010014   4.456408 (  4.516765)
--- Total:           215.960536  14.290549 230.251085 (233.329469)

This is the summary:

Ruby 1.8.6
--- Total: 68.408000 14.751000 83.159000 ( 84.105970)
Ruby 1.9.1
--- Total: 48.499000 15.862000 64.361000 ( 65.568205)
Jruby
--- Total: 46.249000 0.000000 46.249000 ( 46.227999)
Ironruby
--- Total: 215.960536 14.290549 230.251085 (233.329469)

Comments: For the concatenation, in all cases prevails, the operator << instead, include the variables in strings with # (), it may be as efficient use of memory but as a performance is at the bottom. Ironruby fatigue with the strings, the gap is huge with some operators, would enough to use << to almost cancel the gap. A little effort on the string's cycle, if compared with the other three. Very good ruby 1.9.1 with performance similar to Jruby but a memory consumption of only 5Mb against 30Mb used by java. The version 1.8.6 is not so bad, he lost time with gsub (especially compared to jruby).

Numbers

The script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
require "benchmark"
include Benchmark
 
Benchmark.bm(21, "--- Total:") do|b|
  puts "Integer"
  puts "Arithmetic operations 10.000.000:"
  n=10_000_000
  t1 = b.report("x + 2") do
    a = 0
    n.times {|x| a = x + 2 }
  end
  t1 += b.report("x - 1") do
    n.times {|x| a = x - 1 }
  end
  t1 += b.report("x * 3") do
    n.times {|x| a = x * 3 }
  end
  t1 += b.report("x / 2") do
    n.times {|x| a = x / 2 }
  end
  t1 += b.report("x ** 2") do
    n.times {|x| a = x ** 2 }
  end
  t1 += b.report("x % 360") do
    n.times {|x| x % 360 }
  end
  t1 += b.report("Cast") do
    n.times {|x| x.to_s }
    n.times {|x| x.to_f }
  end
 
  puts "Add 10.000.000:"
  n=10_000_000
  t2 = b.report("+=") do
    a = 0
    n.times { a += 1 }
  end
  t2 += b.report("a = a + 1") do
    a = 0
    n.times { a = a + 1 }
  end
  t2 += b.report("<<") do
    a = 0
    n.times { a << 1 }
  end
  t2 += b.report(".next") do
    a = 0
    n.times { a = a.next }
  end
 
  puts "Float"
  puts "Arithmetic operations 10.000.000:"
  n=10_000_000
  t3 = b.report("x + 1.234567") do
    a = 0
    n.times {|x| a = x + 1.234567 }
  end
  t3 += b.report("x - 0.135799") do
    a = 0
    n.times {|x| a = x - 0.135799 }
  end
  t3 += b.report("x * 0.987654") do
    a = 0
    n.times {|x| a = x * 0.987654 }
  end
  t3 += b.report("x / 1.975313") do
    a = 0
    n.times {|x| a = x / 1.975313 }
  end
  t3 += b.report("x ** 1.987654") do
    a = 0
    n.times {|x| a = x ** 1.987654 }
  end
  t3 += b.report("Cast") do
    n.times {|x| x.to_s }
    n.times {|x| x.to_i }
  end
  [t1+t2+t3]
end

Ruby 1.8.6

C:>ruby bench_num.rb
                           user     system      total        real
Integer
Arithmetic operations 10.000.000:
x + 2                  0.981000   0.000000   0.981000 (  0.991485)
x - 1                  0.901000   0.000000   0.901000 (  0.911365)
x * 3                  0.962000   0.000000   0.962000 (  0.961440)
x / 2                  0.911000   0.000000   0.911000 (  0.921380)
x ** 2                 4.316000   0.000000   4.316000 (  4.366540)
x % 360                0.881000   0.000000   0.881000 (  0.961440)
Cast                   4.727000   0.020000   4.747000 (  5.217815)
Add 10.000.000:
+=                     0.952000   0.000000   0.952000 (  0.951425)
a = a + 1              0.901000   0.010000   0.911000 (  0.951425)
<<                     1.312000   0.000000   1.312000 (  1.342010)
.next                  1.312000   0.020000   1.332000 (  1.402100)
Float
Arithmetic operations 10.000.000:
x + 1.234567           2.103000   0.000000   2.103000 (  2.233345)
x - 0.135799           1.983000   0.000000   1.983000 (  2.013015)
x * 0.987654           2.042000   0.000000   2.042000 (  2.053075)
x / 1.975313           2.183000   0.000000   2.183000 (  2.243360)
x ** 1.987654          3.174000   0.000000   3.174000 (  3.184770)
Cast                   4.106000   0.000000   4.106000 (  4.146210)
--- Total:            33.747000   0.050000  33.797000 ( 34.852200)

Ruby 1.9.1

C:>ruby bench_num.rb
                           user     system      total        real
Integer
Arithmetic operations 10.000.000:
x + 2                  3.154000   0.000000   3.154000 (  3.194785)
x - 1                  3.365000   0.000000   3.365000 (  3.415115)
x * 3                  3.415000   0.000000   3.415000 (  3.495235)
x / 2                  3.475000   0.000000   3.475000 (  3.495235)
x ** 2                14.771000   0.010000  14.781000 ( 14.952395)
x % 360                2.914000   0.000000   2.914000 (  3.004500)
Cast                  11.847000   0.000000  11.847000 ( 11.987955)
Add 10.000.000:
+=                     2.544000   0.000000   2.544000 (  2.583870)
a = a + 1              2.524000   0.000000   2.524000 (  2.533795)
<<                     2.233000   0.000000   2.233000 (  2.253375)
.next                  1.963000   0.000000   1.963000 (  1.982970)
Float
Arithmetic operations 10.000.000:
x + 1.234567           3.885000   0.000000   3.885000 (  3.985970)
x - 0.135799           3.886000   0.000000   3.886000 (  3.945910)
x * 0.987654           3.895000   0.000000   3.895000 (  3.945910)
x / 1.975313          12.378000   0.010000  12.388000 ( 12.588855)
x ** 1.987654          5.057000   0.000000   5.057000 (  5.147710)
Cast                  11.106000   0.030000  11.136000 ( 11.286905)
--- Total:            92.412000   0.050000  92.462000 ( 93.800490)

JRuby

C:>jruby bench_num.rb
                           user     system      total        real
Integer
Arithmetic operations 10.000.000:
x + 2                  2.043000   0.000000   2.043000 (  1.863000)
x - 1                  1.803000   0.000000   1.803000 (  1.803000)
x * 3                  1.923000   0.000000   1.923000 (  1.923000)
x / 2                  2.153000   0.000000   2.153000 (  2.153000)
x ** 2                 5.899000   0.000000   5.899000 (  5.899000)
x % 360                1.803000   0.000000   1.803000 (  1.803000)
Cast                   4.527000   0.000000   4.527000 (  4.527000)
Add 10.000.000:
+=                     1.682000   0.000000   1.682000 (  1.682000)
a = a + 1              1.602000   0.000000   1.602000 (  1.602000)
<<                     1.302000   0.000000   1.302000 (  1.302000)
.next                  1.433000   0.000000   1.433000 (  1.433000)
Float
Arithmetic operations 10.000.000:
x + 1.234567           2.363000   0.000000   2.363000 (  2.363000)
x - 0.135799           2.404000   0.000000   2.404000 (  2.404000)
x * 0.987654           2.153000   0.000000   2.153000 (  2.153000)
x / 1.975313           4.487000   0.000000   4.487000 (  4.487000)
x ** 1.987654          5.829000   0.000000   5.829000 (  5.839000)
Cast                   4.146000   0.000000   4.146000 (  4.156000)
--- Total:            47.552000   0.000000  47.552000 ( 47.392000)

IronRuby

C:>ir bench_num.rb
                           user     system      total        real
Integer
Arithmetic operations 10.000.000:
x + 2                  3.925645   0.060086   3.985731 (  4.056075)
x - 1                  1.652376   0.000000   1.652376 (  1.662490)
x * 3                  1.912750   0.000000   1.912750 (  1.972955)
x / 2                  1.982851   0.010014   1.992866 (  2.013015)
x ** 2                 3.895602   0.010014   3.905616 (  3.975955)
x % 360                1.672405   0.010014   1.682419 (  1.692535)
Cast                   6.248986   0.010014   6.259000 (  6.389570)
Add 10.000.000:
+=                     1.672405   0.010014   1.682419 (  1.712565)
a = a + 1              1.742506   0.000000   1.742506 (  1.792685)
<<                     1.472117   0.040058   1.512174 (  1.532295)
.next                  1.672405   0.000000   1.672405 (  1.672505)
Float
Arithmetic operations 10.000.000:
x + 1.234567           1.932779   0.000000   1.932779 (  1.932895)
x - 0.135799           1.952808   0.010014   1.962822 (  2.033045)
x * 0.987654           1.992866   0.000000   1.992866 (  1.992985)
x / 1.975313           3.825501   0.030043   3.855544 (  3.925880)
x ** 1.987654          3.014334   0.000000   3.014334 (  3.034545)
Cast                   5.878453   0.000000   5.878453 (  5.928880)
--- Total:            46.446787   0.190274  46.637061 ( 47.320875)

Summary:

Ruby 1.8.6
--- Total: 33.747000 0.050000 33.797000 ( 34.852200)
Ruby 1.9.1
--- Total: 92.412000 0.050000 92.462000 ( 93.800490)
Jruby
--- Total: 47.552000 0.000000 47.552000 ( 47.392000)
Ironruby
--- Total: 46.446787 0.190274 46.637061 ( 47.320875)

Comments: Marked improvement in the version 1.9.1 which with numbers is three times faster than 1.8.6. The other two are not bad too.
16/08/2009: Only now i see that i mistakenly put shift method (<<) under adding methods.
24/08/2009: I had inverted the 1.8.6's results with those of 1.9.1 ...actually it seemed a bit strange! :-p

Array

The script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
require "benchmark"
include Benchmark
 
Benchmark.bm(21, "Total:") do|b|
  n=100_000
  puts "Create 100.000:"
  t1 = b.report("%w()") do
    n.times { %w(a b c d f e g h j k i l m n o p q r s t u v w y z 0 1 2 3 4 5 6 7 8 9) }
  end
  t1 += b.report("%w''") do
    n.times { %w"a b c d f e g h j k i l m n o p q r s t u v w y z 0 1 2 3 4 5 6 7 8 9" }
  end
  t1 += b.report("split") do
    n.times { "a b c d f e g h j k i l m n o p q r s t u v w y z 0 1 2 3 4 5 6 7 8 9".split(' ') }
  end
  t1 += b.report("[str]") do
    n.times { ["a","b","c","d","f","e","g","h","j","k","i","l","m","n","o","p","q","r","s","t","u","v","w","y","z","0","1","2","3","4","5","6","7","8","9"] }
  end
  t1 += b.report("[num]") do
    n.times { [0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4] }
  end
  t1 += b.report("Array.new(str)") do
    n.times { Array.new(35, "a") }
  end
  t1 += b.report("Array.new(num)") do
    n.times { Array.new(35, 0) }
  end
  t1 += b.report("Array.new(hash)") do
    n.times { Array.new(35, {}) }
  end
 
  n=100_000
  puts "Add 100.000:"
  t2 = b.report("+= ['.']") do
    a = []
    n.times { a += ["."] }
  end
 
  t2 += b.report("+= [0]") do
    a = []
    n.times { a += [0] }
  end
 
  t2 += b.report("<< ['.']") do
    a = []
    n.times { a << ["."] }
  end
 
  t2 += b.report("<< [0]") do
    a = []
    n.times { a << [0] }
  end
 
  t2 += b.report("a = a+['.']") do
    a = []
    n.times { a = a + ["."] }
  end
 
  t2 += b.report("a = a+[0]") do
    a = []
    n.times { a = a + [0] }
  end
 
  n=100_000
  puts "Concatenate 100.000:"
  t3 = b.report("[num]+") do
    n.times { [0,1,2,3,4]+[5,6,7,8,9]+[0,1,2,3,4,5,6,7,8,9] }
  end
  t3 += b.report("[str]+") do
    n.times { ["a","b","c","d","f"]+["e","g","h","j","k"]+["i","l","m","n","o","p","q","r","s","t"] }
  end
  t3 += b.report("[mix]+") do
    n.times { ["a","b","c","d","f"]+[5,6,7,8,9]+["i",0,"m",1,"o",2,"q",3,"s",4] }
  end
  t3 += b.report("[num]<<") do
    n.times { [0,1,2,3,4]<<[5,6,7,8,9]<<[0,1,2,3,4,5,6,7,8,9] }
  end
  t3 += b.report("[str]<<") do
    n.times { ["a","b","c","d","f"]<<["e","g","h","j","k"]<<["i","l","m","n","o","p","q","r","s","t"] }
  end
  t3 += b.report("[mix]<<") do
    n.times { ["a","b","c","d","f"]<<[5,6,7,8,9]<<["i",0,"m",1,"o",2,"q",3,"s",4] }
  end
   t3 += b.report("[num].concat") do
    n.times { [0,1,2,3,4].concat([5,6,7,8,9]).concat([0,1,2,3,4,5,6,7,8,9]) }
  end
  t3 += b.report("[str].concat") do
    n.times { ["a","b","c","d","f"].concat(["e","g","h","j","k"]).concat(["i","l","m","n","o","p","q","r","s","t"]) }
  end
  t3 += b.report("[mix].concat") do
    n.times { ["a","b","c","d","f"].concat([5,6,7,8,9]).concat(["i",0,"m",1,"o",2,"q",3,"s",4])}
  end
  t3 += b.report("union [num]") do
    n.times { [0,14,2,3,4,53,682] | [3,4,53,6,7,84,9] }
  end
  t3 += b.report("union [str]") do
    n.times { ["a","b","c","d","f"] | ["b","d","h","j","k"] }
  end
 
  a=Array.new(100, 0)
  n=1_000_000
  puts "Read 1.000.000:"
  t4 = b.report("each:") do
    n.times { a.each{|x| x} }
  end
  t4 += b.report("map:") do
    n.times { a.map{|x| x} }
  end
 
  puts "Other 10.000:"
  n=10_000
  a=["a",nil,0,"b",1,nil] * 500
  t5 = b.report(".compact:") do
    n.times { a.compact }
  end
  t5 += b.report(".delete(nil):") do
    n.times { a.delete(nil)}
  end
 
  a=[]
  n.times {|x| a << x }
  t5 += b.report("delete:") do
    n.times {|x| a.delete(x) }
  end
  puts "-"*20
  [t1+t2+t3+t4+t5]
end

Ruby 1.8.6

C:>ruby bench_arr.rb
                           user     system      total        real
Create 100.000:
%w()                   0.300000   0.010000   0.310000 (  0.320480)
%w''                   0.300000   0.000000   0.300000 (  0.310465)
split                  2.164000   0.010000   2.174000 (  2.213315)
[str]                  0.310000   0.000000   0.310000 (  0.310465)
[num]                  0.160000   0.030000   0.190000 (  0.220330)
Array.new(str)         0.180000   0.010000   0.190000 (  0.190285)
Array.new(num)         0.151000   0.030000   0.181000 (  0.180270)
Array.new(hash)        0.270000   0.040000   0.310000 (  0.310465)
Add 100.000:
+= ['.']              22.472000   8.272000  30.744000 ( 31.487160)
+= [0]                20.800000   8.602000  29.402000 ( 30.004940)
<< ['.']               0.070000   0.010000   0.080000 (  0.090135)
<< [0]                 0.070000   0.000000   0.070000 (  0.070105)
a = a+['.']           28.321000   7.351000  35.672000 ( 36.514690)
a = a+[0]             25.226000   7.480000  32.706000 ( 33.520205)
Concatenate 100.000:
[num]+                 0.451000   0.030000   0.481000 (  0.490735)
[str]+                 0.581000   0.030000   0.611000 (  0.640960)
[mix]+                 0.521000   0.030000   0.551000 (  0.550825)
[num]<<                0.350000   0.020000   0.370000 (  0.370555)
[str]<<                0.421000   0.031000   0.452000 (  0.450675)
[mix]<<                0.420000   0.010000   0.430000 (  0.430645)
[num].concat           0.341000   0.030000   0.371000 (  0.380570)
[str].concat           0.491000   0.020000   0.511000 (  0.510765)
[mix].concat           0.400000   0.020000   0.420000 (  0.430645)
union [num]            1.032000   0.020000   1.052000 (  1.051575)
union [str]            0.761000   0.080000   0.841000 (  0.881320)
Read 1.000.000:
each:                 16.934000   0.000000  16.934000 ( 17.145680)
map:                  20.750000   1.181000  21.931000 ( 22.243315)
Other 10.000:
.compact:              0.401000   0.131000   0.532000 (  0.530795)
.delete(nil):          4.246000   0.000000   4.246000 (  4.316465)
delete:                4.937000   0.000000   4.937000 (  5.017515)
--------------------
Total:               153.831000  33.478000 187.309000 (191.186350)

Ruby 1.9.1

C:>ruby bench_arr.rb
                           user     system      total        real
Create 100.000:
%w()                   0.520000   0.000000   0.520000 (  0.520780)
%w''                   0.541000   0.000000   0.541000 (  0.550825)
split                  0.781000   0.000000   0.781000 (  0.791185)
[str]                  0.511000   0.000000   0.511000 (  0.520780)
[num]                  0.020000   0.000000   0.020000 (  0.020030)
Array.new(str)         0.170000   0.010000   0.180000 (  0.190285)
Array.new(num)         0.140000   0.000000   0.140000 (  0.140210)
Array.new(hash)        0.141000   0.030000   0.171000 (  0.200300)
Add 100.000:
+= ['.']              22.131000   9.553000  31.684000 ( 32.268330)
+= [0]                16.514000   8.422000  24.936000 ( 25.478160)
<< ['.']               0.010000   0.020000   0.030000 (  0.030045)
<< [0]                 0.030000   0.000000   0.030000 (  0.030045)
a = a+['.']           17.856000   3.946000  21.802000 ( 22.323435)
a = a+[0]             17.024000   8.172000  25.196000 ( 25.788625)
Concatenate 100.000:
[num]+                 0.211000   0.020000   0.231000 (  0.230345)
[str]+                 0.490000   0.000000   0.490000 (  0.500750)
[mix]+                 0.341000   0.000000   0.341000 (  0.340510)
[num]<<                0.140000   0.000000   0.140000 (  0.140210)
[str]<<                0.421000   0.010000   0.431000 (  0.460690)
[mix]<<                0.260000   0.000000   0.260000 (  0.260390)
[num].concat           0.160000   0.000000   0.160000 (  0.160240)
[str].concat           0.471000   0.000000   0.471000 (  0.470705)
[mix].concat           0.320000   0.000000   0.320000 (  0.320480)
union [num]            0.691000   0.020000   0.711000 (  0.721080)
union [str]            0.952000   0.000000   0.952000 (  0.961440)
Read 1.000.000:
each:                  7.861000   0.000000   7.861000 (  7.991970)
map:                  13.169000   1.482000  14.651000 ( 14.822200)
Other 10.000:
.compact:              0.250000   0.130000   0.380000 (  0.380570)
.delete(nil):          2.684000   0.000000   2.684000 (  2.704050)
delete:                4.907000   0.000000   4.907000 (  4.987470)
--------------------
Total:               109.717000  31.815000 141.532000 (144.306135)

JRuby

C:>jruby bench_arr.rb
                           user     system      total        real
Create 100.000:
%w()                   0.251000   0.000000   0.251000 (  0.211000)
%w''                   0.190000   0.000000   0.190000 (  0.190000)
split                  0.370000   0.000000   0.370000 (  0.370000)
[str]                  0.191000   0.000000   0.191000 (  0.191000)
[num]                  0.030000   0.000000   0.030000 (  0.030000)
Array.new(str)         0.080000   0.000000   0.080000 (  0.080000)
Array.new(num)         0.060000   0.000000   0.060000 (  0.060000)
Array.new(hash)        0.100000   0.000000   0.100000 (  0.100000)
Add 100.000:
+= ['.']             143.074000   0.000000 143.074000 (143.074000)
+= [0]               126.099000   0.000000 126.099000 (126.099000)
<< ['.']               0.211000   0.000000   0.211000 (  0.211000)
<< [0]                 0.090000   0.000000   0.090000 (  0.090000)
a = a+['.']          124.536000   0.000000 124.536000 (124.536000)
a = a+[0]            127.672000   0.000000 127.672000 (127.672000)
Concatenate 100.000:
[num]+                 0.120000   0.000000   0.120000 (  0.120000)
[str]+                 0.180000   0.000000   0.180000 (  0.180000)
[mix]+                 0.120000   0.000000   0.120000 (  0.120000)
[num]<<                0.070000   0.000000   0.070000 (  0.070000)
[str]<<                0.211000   0.000000   0.211000 (  0.211000)
[mix]<<                0.110000   0.000000   0.110000 (  0.110000)
[num].concat           0.100000   0.000000   0.100000 (  0.100000)
[str].concat           0.160000   0.000000   0.160000 (  0.160000)
[mix].concat           0.131000   0.000000   0.131000 (  0.131000)
union [num]            0.280000   0.000000   0.280000 (  0.280000)
union [str]            0.300000   0.000000   0.300000 (  0.300000)
Read 1.000.000:
each:                  9.364000   0.000000   9.364000 (  9.364000)
map:                  11.007000   0.000000  11.007000 ( 11.007000)
Other 10.000:
.compact:              0.411000   0.000000   0.411000 (  0.411000)
.delete(nil):          2.904000   0.000000   2.904000 (  2.904000)
delete:                4.687000   0.000000   4.687000 (  4.687000)
--------------------
Total:               553.109000   0.000000 553.109000 (553.069000)

IronRuby

C:>ir bench_arr.rb
                           user     system      total        real
Create 100.000:
%w()                   0.721037   0.000000   0.721037 (  0.721080)
%w''                   0.230331   0.000000   0.230331 (  0.250375)
split                  1.482131   0.000000   1.482131 (  1.482220)
[str]                  0.240346   0.000000   0.240346 (  0.240360)
[num]                  0.100144   0.000000   0.100144 (  0.100150)
Array.new(str)         0.150216   0.000000   0.150216 (  0.150225)
Array.new(num)         0.130187   0.000000   0.130187 (  0.130195)
Array.new(hash)        0.110158   0.000000   0.110158 (  0.120180)
Add 100.000:
+= ['.']              93.234064   9.723982 102.958046 (105.808475)
+= [0]                44.143475   3.294738  47.438213 ( 48.092030)
<< ['.']               0.160230   0.000000   0.160230 (  0.160240)
<< [0]                 0.090130   0.010014   0.100144 (  0.100150)
a = a+['.']           96.779162   9.483637 106.262798 (109.644220)
a = a+[0]             43.823014   3.545098  47.368112 ( 47.921775)
Concatenate 100.000:
[num]+                 0.160230   0.000000   0.160230 (  0.160240)
[str]+                 0.230331   0.000000   0.230331 (  0.240360)
[mix]+                 0.180259   0.000000   0.180259 (  0.180270)
[num]<<                0.090130   0.000000   0.090130 (  0.090135)
[str]<<                0.180259   0.010014   0.190274 (  0.190285)
[mix]<<                0.150216   0.000000   0.150216 (  0.150225)
[num].concat           0.110158   0.010014   0.120173 (  0.120180)
[str].concat           0.220317   0.000000   0.220317 (  0.220330)
[mix].concat           0.180259   0.000000   0.180259 (  0.180270)
union [num]            0.330475   0.000000   0.330475 (  0.340510)
union [str]            0.410590   0.000000   0.410590 (  0.410615)
Read 1.000.000:
each:                 14.040189   0.010014  14.050203 ( 14.181240)
map:                  19.848541   0.020029  19.868570 ( 20.120135)
Other 10.000:
.compact:              1.161670   0.000000   1.161670 (  1.171755)
.delete(nil):         15.462234   0.030043  15.492277 ( 15.833715)
delete:                1.422045   0.000000   1.422045 (  1.472205)
--------------------
Total:               335.572530  26.137584 361.710114 (369.984144)

Summary:

Ruby 1.8.6
Total: 153.831000 33.478000 187.309000 (191.186350)
Ruby 1.9.1
Total: 109.717000 31.815000 141.532000 (144.306135)
Jruby
Total: 553.109000 0.000000 553.109000 (553.069000)
Ironruby
Total: 335.572530 26.137584 361.710114 (369.984144)

Comments: So, in this third test is important to say a few words. Time high of jruby and ironruby is also due to the fact that I wanted to compare the concatenation += with a similar version. Both are very inappropriate for these two interpreters, times are very high and would enough to use operator << to get very different results, in order: 1.8.6 = 61 1.9.1 = 40 jruby = 33 = 60 and ironruby... jruby would be the fastest.
Another curiosity is the use of compact method, besides being more elegant is even faster than delete (nil) with sensitive differences in Ironruby.

Hash

The script to test the Hash is the heaviest as memory's stress test. Frankly, it wasn't in my intentions, but then I thought to hold it for examining the outcomes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
require "benchmark"
include Benchmark
 
n=1_000_000
Benchmark.bm(21, "Total:") do|b|
  puts "Write 1.000.000:"
  h = {}
  t1 = b.report("int => str:") do
    n.times {|x| h[x] = "." }
  end
  h = {}
  t1 += b.report("int => int:") do
    n.times {|x| h[x] = x }
  end
  t1 += b.report("int => [int]:") do
    n.times {|x| h[x] = [x] }
  end
  t1 += b.report(".to_sym => .to_s:") do
    n.times {|x| h[x.to_s.to_sym] = x.to_s }
  end
 
  puts ":sym => str 1.000.000:"
  t2 = b.report("Each:") do
    h.each {|k,v| k; v}
  end
 
  t2 += b.report("each_key:") do
    h.each_key {|k| k}
  end
 
  t2 += b.report("each_value:") do
    h.each_value {|v| v}
  end
 
  t2 += b.report("read by key:") do
    h.each {|k,v| h[k]}
  end
 
  h1=h
 
  t3 = b.report("5 invert:") do
    5.times { h.invert }
  end
 
  h=h1
  t3 += b.report("1000 shift:") do
    1000.times { h.shift }
  end
 
  h=h1
  t3 += b.report("1000 delete:") do
    1000.times {|x| h.delete(x) }
  end
 
  h=h1
  t3 += b.report("all delete:") do
    h.each_key {|k| h.delete(k)}
  end
 
  [t1+t2+t3]
end

Ruby 1.8.6

C:>ruby bench_hsh.rb
                           user     system      total        real
Write 1.000.000:
int => str:            0.851000   0.030000   0.881000 (  0.881320)
int => int:            1.021000   0.090000   1.111000 (  1.141710)
int => [int]:          0.791000   0.030000   0.821000 (  0.841260)
.to_sym => .to_s:      6.400000   0.080000   6.480000 (  6.509750)
:sym => str 1.000.000:
Each:                  2.553000   0.090000   2.643000 (  2.684020)
each_key:              0.481000   0.000000   0.481000 (  0.490735)
each_value:            0.491000   0.000000   0.491000 (  0.490735)
read by key:           2.854000   0.040000   2.894000 (  2.904350)
5 invert:             31.185000   0.791000  31.976000 ( 32.438585)
1000 shift:           37.604000   0.010000  37.614000 ( 38.177180)
1000 delete:           0.000000   0.000000   0.000000 (  0.000000)
all delete:            1.442000   0.010000   1.452000 (  1.452175)
Total:                85.673000   1.171000  86.844000 ( 88.011820)

Ruby 1.9.1

C:>ruby bench_hsh.rb
                           user     system      total        real
Write 1.000.000:
int => str:            0.721000   0.100000   0.821000 (  0.841260)
int => int:            0.590000   0.140000   0.730000 (  0.731095)
int => [int]:          0.391000   0.020000   0.411000 (  0.440660)
.to_sym => .to_s:      4.957000   0.320000   5.277000 (  5.327980)
:sym => str 1.000.000:
Each:                  0.691000   0.050000   0.741000 (  0.801200)
each_key:              0.461000   0.000000   0.461000 (  0.470705)
each_value:            0.500000   0.000000   0.500000 (  0.520780)
read by key:           1.022000   0.011000   1.033000 (  1.051575)
5 invert:             33.939000   1.071000  35.010000 ( 35.603325)
1000 shift:           48.800000   0.020000  48.820000 ( 49.474100)
1000 delete:           0.000000   0.000000   0.000000 (  0.000000)
all delete:            1.432000   0.010000   1.442000 (  1.472205)
Total:                93.504000   1.742000  95.246000 ( 96.734885)

JRuby

C:>jruby bench_hsh.rb
                           user     system      total        real
Write 1.000.000:
int => str:            2.113000   0.000000   2.113000 (  1.933000)
int => int:            0.721000   0.000000   0.721000 (  0.721000)
int => [int]:          1.022000   0.000000   1.022000 (  1.022000)
.to_sym => .to_s:     34.641000   0.000000  34.641000 ( 34.641000)
:sym => str 1.000.000:
Each:                  0.541000   0.000000   0.541000 (  0.541000)
each_key:              0.191000   0.000000   0.191000 (  0.191000)
each_value:            0.240000   0.000000   0.240000 (  0.240000)
read by key:           0.761000   0.000000   0.761000 (  0.761000)
5 invert:            Error: Your application used more memory than the safety cap.

IronRuby

C:>ir bench_hsh.rb
                           user     system      total        real
Write 1.000.000:
int => str:            2.183139   0.030043   2.213182 (  2.213315)
int => int:            1.211742   0.030043   1.241786 (  1.291935)
int => [int]:          1.712462   0.010014   1.722477 (  1.732595)
.to_sym => .to_s:      7.460728   0.120173   7.580901 (  7.781655)
:sym => str 1.000.000:
Each:                  1.111598   0.000000   1.111598 (  1.131695)
each_key:              0.340490   0.000000   0.340490 (  0.350525)
each_value:            0.330475   0.010014   0.340490 (  0.350525)
read by key:           1.021469   0.000000   1.021469 (  1.031545)
5 invert:              5.588035   0.350504   5.938539 (  7.381055)
1000 shift:            0.020029   0.000000   0.020029 (  0.190285)
1000 delete:           0.020029   0.000000   0.020029 (  0.080120)
all delete:            1.031483   0.020029   1.051512 (  1.061590)
Total:                22.031680   0.570821  22.602501 ( 24.596839)

Summary:

Ruby 1.8.6
Total: 85.673000 1.171000 86.844000 ( 88.011820)
Ruby 1.9.1
Total: 93.504000 1.742000 95.246000 ( 96.734885)
Jruby
*** Out of memory ***
Ironruby
Total: 22.031680 0.570821 22.602501 ( 24.596839)

Comments: JRuby has not concluded the test to an error of "out of memory", the java process has come to occupy 600Mb in the test where you make an {}.invert, reaching the limit of the JVM. The least greedy of memory was ruby 1.8.6 with "only" 300Mb while 1.9.1 was almost fixed at 530Mb, not increased, as if there was a wall. There was not, instead, for Ironruby that has exceeded the barrier of 600Mb but with great results, the inversion executed in 5 seconds, compared with 33 of 1.9.1!

The same test with 2Gb of ram:

Ruby 1.8.6

C:>ruby bench_hsh.rb
                           user     system      total        real
Write 1.000.000:
int => str:            0.811000   0.060000   0.871000 (  0.871252)
int => int:            1.081000   0.050000   1.131000 (  1.141642)
int => [int]:          0.751000   0.030000   0.781000 (  0.801152)
.to_sym => .to_s:      6.299000   0.130000   6.429000 (  6.469302)
:sym => str 1.000.000:
Each:                  2.474000   0.060000   2.534000 (  2.553672)
each_key:              0.491000   0.000000   0.491000 (  0.490706)
each_value:            0.500000   0.000000   0.500000 (  0.500720)
read by key:           2.834000   0.080000   2.914000 (  2.964263)
5 invert:             30.454000   0.992000  31.446000 ( 31.885849)
1000 shift:           38.285000   0.020000  38.305000 ( 38.765743)
1000 delete:           0.000000   0.000000   0.000000 (  0.000000)
all delete:            1.472000   0.010000   1.482000 (  1.512174)
Total:                85.452000   1.432000  86.884000 ( 87.956475)

Ruby 1.9.1

C:>ruby bench_hsh.rb
                           user     system      total        real
Write 1.000.000:
int => str:            0.701000   0.090000   0.791000 (  0.790640)
int => int:            0.661000   0.100000   0.761000 (  0.780631)
int => [int]:          0.360000   0.020000   0.380000 (  0.390316)
.to_sym => .to_s:      4.947000   0.380000   5.327000 (  5.524472)
:sym => str 1.000.000:
Each:                  0.631000   0.041000   0.672000 (  0.690558)
each_key:              0.451000   0.000000   0.451000 (  0.450365)
each_value:            0.490000   0.000000   0.490000 (  0.490397)
read by key:           0.892000   0.030000   0.922000 (  0.940761)
5 invert:             27.760000   6.299000  34.059000 ( 34.547961)
1000 shift:           48.289000   0.020000  48.309000 ( 48.789488)
1000 delete:           0.000000   0.000000   0.000000 (  0.000000)
all delete:            1.072000   0.370000   1.442000 (  1.441166)
Total:                86.254000   7.350000  93.604000 ( 94.836755)

JRuby

C:>jruby bench_hsh.rb
                           user     system      total        real
Write 1.000.000:
int => str:            2.261000   0.000000   2.261000 (  2.081000)
int => int:            0.760000   0.000000   0.760000 (  0.760000)
int => [int]:          1.051000   0.000000   1.051000 (  1.051000)
.to_sym => .to_s:     35.694000   0.000000  35.694000 ( 35.694000)
:sym => str 1.000.000:
Each:                  0.481000   0.000000   0.481000 (  0.481000)
each_key:              0.190000   0.000000   0.190000 (  0.190000)
each_value:            0.190000   0.000000   0.190000 (  0.190000)
read by key:           0.701000   0.000000   0.701000 (  0.701000)
5 invert:            Error: Your application used more memory than the safety cap.

C:>jruby bench_hsh.rb -J-Xmx1500m
                           user     system      total        real
Write 1.000.000:
int => str:            1.612000   0.000000   1.612000 (  1.562000)
int => int:            0.842000   0.000000   0.842000 (  0.842000)
int => [int]:          1.101000   0.000000   1.101000 (  1.101000)
.to_sym => .to_s:     35.341000   0.000000  35.341000 ( 35.341000)
:sym => str 1.000.000:
Each:                  0.431000   0.000000   0.431000 (  0.431000)
each_key:              0.180000   0.000000   0.180000 (  0.180000)
each_value:            0.190000   0.000000   0.190000 (  0.200000)
read by key:           0.701000   0.000000   0.701000 (  0.691000)
5 invert:             11.076000   0.000000  11.076000 ( 11.076000)
1000 shift:            0.000000   0.000000   0.000000 (  0.000000)
1000 delete:           0.000000   0.000000   0.000000 (  0.000000)
all delete:            0.912000   0.000000   0.912000 (  0.912000)
Total:                52.385999   0.000000  52.385999 ( 52.335999)

IronRuby

C:>ir bench_hsh.rb
                           user     system      total        real
Write 1.000.000:
int => str:            2.283283   0.090130   2.373413 (  2.363398)
int => int:            1.201728   0.030043   1.231771 (  1.241786)
int => [int]:          1.792578   0.020029   1.812606 (  1.862678)
.to_sym => .to_s:      7.340555   0.120173   7.460728 (  7.590915)
:sym => str 1.000.000:
Each:                  1.091570   0.000000   1.091570 (  1.141642)
each_key:              0.310446   0.000000   0.310446 (  0.310447)
each_value:            0.360518   0.000000   0.360518 (  0.360518)
read by key:           1.001440   0.000000   1.001440 (  1.001440)
5 invert:              4.816926   0.070101   4.887027 (  4.917070)
1000 shift:            0.010014   0.000000   0.010014 (  0.010014)
1000 delete:           0.010014   0.000000   0.010014 (  0.010015)
all delete:            1.061526   0.000000   1.061526 (  1.071541)
Total:                21.280600   0.330475  21.611075 ( 21.881464)

Summary:

Ruby 1.8.6
Total: 85.452000 1.432000 86.884000 ( 87.956475)
Ruby 1.9.1
Total: 86.254000 7.350000 93.604000 ( 94.836755)
Jruby
Total: 52.385999 0.000000 52.385999 ( 52.335999)
Ironruby
Total: 21.280600 0.330475 21.611075 ( 21.881464)

Comments: JRuby hangs again and always with a process of 600Mb, so I increased the cap to 1.5 Gb memory allowing it to finish even with a good result but the process has reached monstrous size, has passed 1Gb. Ruby 1.8.6 again the least greedy with 300Mb and again 530Mb for the 1.9.1. Both have high time with the invert method and in particular with the shift, contrary for the two others. Ironruby still the fastest with a process that detects an huge amount of memory, coming to allocate almost 700Mb.
Deleting the elements has always been fast even if they increased the number, maybe I did not check well that were not performed in a single call, however, I shall from this result.

Conclusions:

Each interpreter has its areas where it excels, Ironruby when he does, he does well, outdistanced the others. JRuby also has taken its triumphs, maybe I had a little more expectations from version 1.9.1 although I believe it is not a demerit but were the others to improve much in recent months. I was very impressed by the version 1.8.6 with this "new" patch 368 with, or better, a different compiled (mingw32), that much improved performance by shortening the distances with the new 1.9, while not having a VM. It is also the most balanced without high or low and to consider that there is still the most used, and more compatible with the largest number of buds.

I hope this article was interesting, the next will include a comparison with also python 2.6.2 and the newest 3.1.1 which is very very fast. Hola!

 
Comments Off

Posted in IronRuby .NET, JRuby, Ruby