Friday, February 28, 2014

A Speed Comparison Born From Curiosity (GoLang and Ruby)

I was a little curious about the speed of a Raspberry Pi versus my older model MacBook Pro.

The Raspberry Pi is the B model with 512 MB of RAM and a 700 MHz processor which Linux is reporting as an ARM6-compatible processor (CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d).

The MacBook Pro is a 2.4 GHz core 2 duo running 10.9.1 with 4 GB RAM.

I wasn't looking for anything necessarily in depth as a benchmark. I simply whipped up a quick counting loop in Go (1.2 release) and compiled it for Darwin and another for ARM. Ran each with the time command. Here's the source:

package main

import "fmt"

func f() {
        for i := 0; i < 1000000; i++ {
                fmt.Println(i)
        }
}

func main() {
        f()
}

Results?

On the Mac:

real 0m9.875s
user 0m0.922s
sys 0m1.709s

On the Raspberry Pi:

real 12m41.821s
user 1m56.220s
sys 3m43.170s

...holy crap.

I mean, I expected a difference, but I guess I didn't expect quite that much of a difference.

Wow.

If I round the Mac to 10 seconds and the Pi to 760 seconds, that's saying the Mac is 76 times faster at executing this loop using Go.

When I wanted to play with programming I originally I was going to use Ruby. What if I created a stupid simple Ruby loop that counts to the same number? The source:

for n in 1...1000000 do
        puts "#{n}"
end

Yes, I know there's a preferred syntax that I didn't follow for Ruby, I was just throwing a quick throwaway loop at 2 in the morning. Don't judge me.

The results?

On the Mac:

real    0m16.523s
user 0m5.210s
sys 0m3.543s

On the Raspberry Pi:

real 9m23.992s
user 2m10.790s
sys 1m55.610s

Well, this is interesting.

The Mac was about 17 seconds. The Pi was about 560 seconds. That means the Mac was about 33 times faster.

The Mac was 76 times faster with Go but only 33 times faster with Ruby.

Does this really mean anything? Not really. There are other things at play that could affect the speed of the applications; these platforms are really very different beasts. All you can really say is that the Pi is relatively slow compared to an older-generation Mac. Kind of expected. The only surprise is the magnitude of difference.

Multiple runs of the application and script weren't even entirely consistent; probably due to caching, or background tasks eating processor cycles when I wasn't aware of it (if I really wanted to control conditions I'd run this several more times, recording each time, and make sure my OS was doing as little as possible while conducting the test and not having, say, a web browser open.)

(NINJA EDIT - this may be more due to implementation of the code used to write output to the console and to what degree I/O is blocked in the process. See near the end of the post for my second NINJA EDIT.)

Just for giggles, I tried running the tests on another Macintosh; this one a MacBook Pro with 16 gig of RAM and a 2.6 GHz core i7 processor. The Go executable clocked in with:

real 0m4.559s
user 0m0.587s
sys 0m1.049s

...and the Ruby script hit with:

real 0m6.170s
user 0m2.945s
sys 0m1.956s

Anyone have an explanation for why I got these results? Feel free to leave a comment.

NINJA EDIT:
After further goofing around and posting about this on Stack Exchange, I had speculated that output to the console was somehow blocked for Ruby, and the answers seemed to confirm that (at least for Ruby. Ruby I/O is apparently a blocking operation most of the time?) I should have thought of this before, but they suggested that the best way to get the run-time was to redirect output to /dev/null.

So, using "time <executable> >& /dev/null", I got the following results:

On the 4 GB, 2.4 GHz Mac:
The Go executable:
 real 0m1.416s
user 0m0.752s
sys 0m0.575s

The Ruby script:
real 0m1.242s
user 0m1.170s
sys 0m0.030s

Now for the Raspberry Pi:
The Go executable:
real 0m17.345s
user 0m14.620s
sys 0m2.700s

The Ruby script:
real 0m34.479s
user 0m34.360s
sys 0m0.060s

Well...wow? That "puts" operation must really be hindering the Ruby script. Ouch! And that Go executable...Just wow. That is really, really fast, compared to when I run it to the console instead of redirecting output.


No comments:

Post a Comment