13,294,516 members (59,609 online)
alternative version

#### Stats

27.3K views
7 bookmarked
Posted 8 Nov 2012

# Comparing Ruby and C# Performance

, 8 Nov 2012
 Rate this:
A quick test of Ruby performance vs. C#

## Introduction

As I'm in the middle of learning Ruby and Ruby on Rails, I wanted to do a quick comparison of Ruby vs C#, knowing quite well that C# will outperform Ruby, but I wanted to get some idea by how much.  This site indicates that Ruby is about 25 times slower on average, but I wanted to see for myself.  As it turns out, Ashraff Ali Wahab had a couple days ago posted the article Eratosthenes/Sundaram/Atkins Sieve Implementation in C#, and I figured this would be a quick way to write some tests.

This is obviously not conclusive - it's a bit like comparing apples and oranges at the code level, especially since I tried to leverage the syntax of Ruby to my current level of understanding.  Also, I decided to give IronRuby a try as well, however the tests were inconclusive as the program failed to complete.

## Source Code

### C#

Please refer to Ashraff Ali Wahab article for the C# source code.

### Ruby

#### Brute Force Algorithm

```def BruteForce(topCandidate)
totalCount = 1
isPrime = true

3.step(topCandidate, 2) do |i|
j=3

while j*j <= i && isPrime
isPrime = false if i%j==0
j += 2
end

isPrime ? totalCount += 1 : isPrime = true
end

totalCount
end```

#### Sieve of Eratosthenes Algorithm

```def SieveOfEratosthenes(topCandidate)
myBA1 = Array.new(topCandidate + 1) {true}
myBA1[0] = myBA1[1] = false
thisFactor = 2

while thisFactor * thisFactor <= topCandidate do
mark = thisFactor + thisFactor
mark.step(topCandidate+1, thisFactor) {|n| myBA1[n] = false}

thisFactor += 1

while !myBA1[thisFactor] do
thisFactor += 1
end

end

myBA1.count(true)
end```

#### Sieve of Sundaram Algorithm

```def SieveOfSundaram(topCandidate)
k = topCandidate / 2
myBA1 = Array.new(k + 1) {true}
myBA1[0] = myBA1[k] = false

for i in 1..k do
denominator = (i << 1) + 1
maxVal = (k - i) / denominator
i.step(maxVal+1, 1) {|n| myBA1[i + n * denominator] = false}

# this version takes .20 seconds longer to run 1M iterations!
# for n in i..maxVal+1 do
# myBA1[i + n * denominator] = false
# end
end

myBA1.count(true) + 1
end```

#### "Main"

```def main
max = 1000000
startTime = Time.now()
primes = BruteForce(max)
endTime = Time.now()
elapsed = endTime - startTime
printf("Elapsed time for Brute Force : %f Primes = %d\n", elapsed, primes)

startTime = Time.now()
primes = SieveOfEratosthenes(max)
endTime = Time.now()
elapsed = endTime - startTime
printf("Elapsed time for Sieve of Eratosthenes: %f Primes = %d\n", elapsed, primes)

startTime = Time.now()
primes = SieveOfSundaram(max)
endTime = Time.now()
elapsed = endTime - startTime
printf("Elapsed time for Sieve of Sundaram : %f Primes = %d\n", elapsed, primes)
end```

## The Results

As you can see from these screenshots:

Ruby is:

• about 5 times slower for the brute force algorithm
• about 19 times slower for the Eratosthenes and Sundaram algorithms

For my purposes, that's essentially inline with the shootout website I mentioned in the Introduction.

Sadly, the IronRuby program did not complete:

Dying on this line:

`myBA1.count(true)`

But the brute force algorithm was consistently almost twice as slow.

## Running on a Virtual Box

I'm also running Ubuntu on Virtual Box (2GB RAM, 3 processors) and was pleased with the results:

## Conclusion

While not conclusive, it was a useful exercise to go through.  Note particularly the commented out Ruby code:

```i.step(maxVal+1, 1) {|n| myBA1[i + n * denominator] = false}

# this version takes .20 seconds longer to run 1M iterations!
# for n in i..maxVal+1 do
# myBA1[i + n * denominator] = false
# end
```

The "for" loop version takes almost 50% longer!  That is a significant and worthwhile discovery, and it essentially makes sense -- the `step` function is a library implementation (and I would assume therefore compiled) whereas the `for` loop I would imagine is constantly being interpreted.  Still, it's a significant difference, especially considering that the block `{|n| myBA1[i + n * denominator] = false}` theoretically is implemented as a function call.

Also, it was disappointing that the IronRuby code failed.  I was hoping that something this "simple" would not have issues.

Lastly, please do not take this as a detraction to Ruby!  This is an amazing language and for many purposes, performance is not the most important concern - interactions with a database and network latency (if you're thinking of Ruby on Rails) will often contribute more to the perception of performance than the language performance.

Also, there appear to be some compilers available, for example Rubinius as well as The Ludicrous JIT Compiler. The former looked much too complicated to try, and the latter, Ludicrous, I did try but was not successful with the installation.  Given that the creator claims "Though still in the experimental stage, its performance is roughly on par with YARV", it doesn't seem that helpful, given that:  "Probably the most exciting and visible change in Ruby 1.9 is the addition of a bytecode interpreter for Ruby. The YARV (Yet Another Ruby VM) interpreter was integrated into the Ruby project, replacing the interpreter created by Matz (aka MRI, Matz's Ruby Interpreter)." (read here).

## Share

 United States
Marc is the creator of two open source projects, MyXaml, a declarative (XML) instantiation engine and the Advanced Unit Testing framework, and Interacx, a commercial n-tier RAD application suite.  Visit his website, www.marcclifton.com, where you will find many of his articles and his blog.

Marc lives in Philmont, NY.

## You may also be interested in...

 View All Threads First Prev Next
 My vote of 5 Ahmed Ibrahim Assaf6-Dec-12 0:23 Ahmed Ibrahim Assaf 6-Dec-12 0:23
 Last Visit: 31-Dec-99 19:00     Last Update: 14-Dec-17 3:47 Refresh 1