Monday, June 29, 2009

Benchmarking the iPhone, and lots of other devices too

Benchmarking has been around for years, and I started playing around with writing them back in college.  I recall an assembly language class were the assignment was to implement the Sieve of Eratosthenes in as few bytes as possible. I "won" the assignment by doing it in 24 (or was it 25, too many years ago!) bytes, but that got me started on benchmarking as I instrumented the code to time how long it took and then proceeded to run it on all the different machines I could to see which one was the fastest.


Clearly though, having a benchmark written in 8086 assembly language had limited usefulness, so in later years I rewrote it in C and added several other standard algorithms to the stable that were executed including calculating PI, a selection sort, and computing Ackermann's function to test recursive performance. I proceeded to run it on every machine I could from PCs running MS-DOS to workstations running Solaris to PPC machines running LynxOS and AIX. In later years, I ran the same benchmark on UltraSPARC, SGI MIPS, and DEC Alpha machines as well as today's dual-core Intel chips. Somewhere along the line I starting writing more in Java than C and I ported the benchmark to Java to see how it compared, and several years ago I began using BlackBerry's and wrote a Java ME version.


As you can imagine given the wide range of machines I've run it on in the past, having an iPhone was just begging to run it there too. While I have creating a proper iPhone app version on my list of things to do, thankfully a jailbroken iPhone makes it pretty easy to run the C and Java versions I already had. A sampling of results appears below, but the summary for the iPhone is that the native version is about 5 times faster than the Java one and ever so slightly faster than a 75 MHz Pentium 5 of yesteryear.








































































































































 MachineLanguageMathArraySortSieveAckermannTotal
Motorola L6Java ME0.110.190.230.130.190.17
BlackBerry Curve (OS 4.5)Java ME0.952.212.961.722.961.81
iPhone 3GJava SE12.44.794.643.285.014.95
Intel 486DX2-66 (Linux)C101010101010
SPARC-20 (Solaris)C66.420.317.620.14.112.1
Pentium 5 75 MHz (Linux)C21.319.628.623.233.424.2
iPhone 3GC65.92123.419.246.727.9
DEC Alpha 275 MHz (OSF/1)C111.493.663.141.276.168.6
Pentium 600 MHz (Linux)Java SE191.9106.199.168.978.296.1
Pentium 600 MHz (Linux)C216.4319.3219.8171.5131.2194.1
MacBook Pro 2.33 GHzJava SE6551096794549334587
MacBook Pro 2.33 GHzC1089241366480013561037


You may also view the full list that I have maintained over the years.  You'll notice that I did my initial calibration on a 66 MHz 486 DX-2 so that it scores 10 in each of the tests.


Now, I'll be the first to admit that my benchmark is pretty simplistic and thus shouldn't be be the end all be all testing to compare machines or platforms. The results can also be significantly affected by the quality of the C compiler or JVM being used. However, the results can provide a rough comparison and are at least fun to look at.


For example a SPARC-20 has terrible performance with deep recursion. And as noted above the JVM on the iPhone is about 5 times slower than a native app whereas on an x86 box the JVM is about half as fast as native.


While I've run the benchmark on quite a few machines, I'd love to add more to the list.  If you'd like to run it, here is the binaries in a variety of formats:




  • Linux on x86 - Download the binary, set the executable flag, and execute with "./sci <iterations>". On most of today's faster machines iterations should be 10,000 to have reasonable results.

  • OS X on x86 - Download the binary, set the executable flag, and execute with "./sci <iterations>". On most of today's faster machines iterations should be 10,000 to have reasonable results.

  • OS X on ARM/iPhone - Download the binary, use ssh/scp to get it on your jailbroken iPhone, and execute with "./sci <iterations>". The default iterations should be fine.

  • Solaris on x86 - Download the binary, set the executable flag, and execute with "./sci <iterations>". On most of today's faster machines iterations should be 10,000 to have reasonable results.

  • Solaris on SPARC - Download the binary, set the executable flag, and execute with "./sci <iterations>". On most of today's faster machines iterations should be 10,000 to have reasonable results.

  • AIX on RS/6000 - Download the binary, set the executable flag, and execute with "./sci <iterations>". On most of today's faster machines iterations should be 10,000 to have reasonable results.

  • Java SE - Download the jar and execute it on any machine you have a JVM with "java -jar SCIJ.jar <iterations>". On most of today's faster machines iterations should be at least 5,000.

  • Java ME devices - Point your phone/device browser at the link and it should prompt to install the application. Run the app and if it executes in less than a few seconds change the iterations to a larger number to make it more accurate in calculating the benchmark.



If you do run the benchmark, please post a comment on this blog entry with the chipset, clock-speed, operating system, and results from each of the tests that the program displays. As soon as someone jailbreaks an iPhone 3G S, it would be great to add that result to the list.


Enjoy!