30 September 2011

Speed time trials and the Fibonacci sequence

Over the past couple days I've had a little free time at work, so I decided to do an academic experiment to compare computation times between a few languages for generating the Fibonacci sequence.

The languages I originally started with were Ruby and Java, but later expanded to include JRuby and C. Any reasonable programmer would be able to align these and say this is how they expect them to align--and for the most part, they would be right! However, as a thought experiment, why not try it?

I've already said that we're doing the Fibonacci sequence and we'll use recursion first just because recursion is fun and it will really tax the system. Here's the pseudo code for every implementation:


If args.length < 1, print "usage: use an argument for calculation", exit
for (0..arg[0])
print(fib(i))
next

int fib(n)
if n < 2, return 1
else return fib(n-1) + fib(n-2)

So as you can see, this is a VERY simple program. My expectations were that the languages would be ranked like so:
  • C
  • Java
  • JRuby
  • Ruby
And I was wrong. Without doing any compiler optimizations, here are the times:
  • C - 0m1.778s
  • Java - 0m0.933s
  • JRuby - 0m11.043s
  • Ruby - 3m31.096s
What?? Java is faster than C? That can't be right... can it? Optimizing the C code through the compiler speeds it up some; it's now at 0m0.766s. Shaved off over a second? Huh. It seems to me that something is up, so after consulting the google, I find this article. So Java seems to be helping out a little bit behind the scenes.

Alright, how do we prevent that and still get some good comparisons? Well, I think instead of letting Java do its JIT, I modified the program to get rid of the loop; just do one number at a time. Here are those times:
  • C - 0m1.100s
  • C (optimized) - 0m0.466s
  • Java - 0m0.625s
  • JRuby - 0m7.164s
  • Ruby - 2m7.298s
Well, Java still seems to be a contender, but that's expected right? We're still calling the same method over and over, so the JIT compiler is bound to still be able to help out. Is that a bad thing? No, you're getting near C-level performance out of the JVM. Pretty cool, actually.

So what? Why am I even testing Ruby? Just to see the performance comparison, really. I've just recently started using it and figured this would be a good comparison of computation time, as well as language syntax. I never expected an interpreted language to be on par with a compiled language--at least for this test.

Ruby is great for lots of things, it's easy to learn, easy to read, but as we see, not great at number crunching. At the same time, putting it on top of the JVM (via JRuby), we get closer to a comparable result with C and Java.

If we use the iterative method for finding Fibonacci numbers, we get these numbers:
  • C - 0m0.011s
  • C (optimized) - 0m0.002s
  • Java - 0m0.102s
  • JRuby - 0m0.431s
  • Ruby - 0m0.004s
Hmm... Does that make sense? Well, the JVM has to start up which takes some time, so yeah. But Ruby faster than C? I looked a little more at what I was doing in my code. Suspect was the fact that I was printing every number out to the screen. I removed that, in effect just testing looping and some simple math, and here's the numbers: (fib(1000))
  • C - 0m0.002s
  • C (optimized) - 0m0.002s
  • Java - 0m0.099s
  • JRuby - 0m0.421s
  • Ruby - 0m0.004s
Stepping up the number, Ruby starts becoming less efficient. So an interpreted language can perform reasonably as well as optimized C. Interesting.

In the end, it's a fun test that drives home the point that when you're solving a problem, understanding it and the capabilities and pitfalls of your language makes a difference. Wield your tools appropriately.

22 September 2011

Third-party mice && OSX Lion

I was having a tough time getting used to both the Magic Pad and Magic Mouse with OSX Lion, so I decided to go back to my trusty three button. However, with the changes to scroll movement, inertial scrolling and this crazy idea of a third button on a mouse, I had to do some digging to "customize" Lion to work the way I wanted.

First, it's not hard to find the option to turn the "reverse" scrolling off; it's under the mouse preferences saying "Move content in the direction of finger movement when scrolling or navigating." While this isn't the most concise explanation, it's certainly verbose.

Second, I wanted to turn off the inertia when scrolling. This works phenomenally when using either of the Apple products, it doesn't work like I'd like (or what I'm used to; since I switch systems so often). This wasn't quite as easy to find, but luckily, it's out there. This article explains how to change it.

Finally, I like using a mouse that has a thumb button. To use and configure this to my liking, I found some software called USB Overdrive. It has options for all sorts of third party keyboards and mice. This section will help with the various parts of it and how to get it setup for your liking.