Showing posts with label Python. Show all posts
Showing posts with label Python. Show all posts

Saturday, 22 March 2014

Programming language (micro) benchmark

Out of curiosity, arising from a discussion on the Raspberry Pi forum, I did some micro benchmarking of C, Java and Python programming languages on Raspberry Pi. The application loops through numbers from 3 to 10000 and checks whether it is a prime number. I tried my best to make the code as close the same in all three languages (even not using boolean types) and eliminate any interference like console output. Also I did repeat the tests multiple times; seeing only some milliseconds deviation between runs.

Python code:
result = 0
result |= 2
for i in range(3,10001):
    prime = 1
    for j in range(2, i):
        k = i/j
        l = k*j
        if l == i:
            prime = 0
    if prime == 1:
        result |= i
print result

Saved as prime2.py and ran timing the execution:
$ time python prime2.py
16383

real    8m25.081s
user    8m7.960s
sys     0m1.230s

$ python --version
Python 2.7.3
...yes, that is 8 and a half minutes.

C code (repeats the test function 10 times to match Java...):
#include  <stdio.h>
int test() {
  int result = 0;
  result |= 2;
  int i;
  for (i=3;i<=10000;i++) {
    int prime = 1;
    int j;
    for (j=2;j<i;j++) {
      int k = i/j;
      int l = k*j;
      if (l==i) prime = 0;
    }
    if (prime) result |= i;
  }
  printf("%i\n", result);
}

int main() {
  int i;
  for (i = 0; i < 10; i++) {
    test();
  }
}

Saved as prime2.c, compiled with gcc -O2 -o prime2 prime2.c (with typical optimisation level 2) and ran:
$ time ./prime2
16383
16383
16383
16383
16383
16383
16383
16383
16383
16383

real    0m35.957s
user    0m35.780s
sys     0m0.070s

$ gcc --version
gcc (Debian 4.6.3-14+rpi1) 4.6.3
...which is 36 seconds for 10 rounds = less than 4 seconds for the same one round as in Python... (gcc (Debian 4.6.3-14+rpi1) 4.6.3)

Java code (repeats the test function 10 times to eliminate the effect of virtual machine start up time and possibly give the Hotspot compiler a chance to kick in):
public class Prime2 {

  public static void main(String [] args) {
    for (int i = 0; i < 10; i++) {
      test();
    }
  }

  public static void test() {
    int result = 0;
    result |= 2;
    for (int i=3;i<=10000;i++) {
      boolean prime = true;
      for (int j=2;j<i;j++) {
        int k = i/j;
        int l = k*j;
        if (l==i) prime = false;
      }
      if (prime) result |= i;
    }
    System.out.println(result);
  }
}

Saved as Prime2.java, compiled with javac Prime2.java and ran:
$ time java Prime2
16383
16383
16383
16383
16383
16383
16383
16383
16383
16383

real    0m33.490s
user    0m33.130s
sys     0m0.240s

$ java -version
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b36e)
Java HotSpot(TM) Client VM (build 25.0-b04, mixed mode)
...which is pretty impressive - even slightly faster than C - the Oracle guys have done a good job with optimising the Java platform for RPi.

Of course this is just a micro benchmark and one cannot draw too definite conclusions from the results. Also there are other aspects (accessibility, productivity, availability of domain specific libraries etc.) to consider when choosing a programming language.

Sunday, 3 March 2013

Coding Gold Dust: How to break out from an infinite loop (in Python)

Infinite loops have many uses... In the earlier post I presented a 'Pythonian' way of writing an infinite loop. Obviously in some cases, the loop needs to be 'near infinite' - without the user forcible breaking the execution with Ctrl+C. The simplest way is to use the break command:
while True:
    do_something
    if some_condition:
        break

For example, reading some input from the user ('the oracle answers'):
while True:
    s = raw_input("What's your question?")
    if s == "who are you":
        print "Raspberry Pi!"
    if s == "quit":
        break

Many other programming languages have the break command as well.

But if the body of the while loop grows longer - spanning maybe even more than a 'screenful', it might become not so readable anymore. If there are certain defined exit condition(s), why have a while True declaration at all. Wouldn't it be better to tell the reader of the code that there is going to be something breaking out of the loop? For this we can use an exit variable:
done = False
while not done:
    s = raw_input("What's your question?")
    if s == "who are you":
        print "Raspberry Pi!"
    if s == "quit":
        done = True
...the 'while not done' should read pretty clearly for a human and as not False equals True, the loop runs as long as the variable value is False.

Of course, there might be multiple such loops in a lengthier program and the exit condition might change. So it should make sense to use an exit variable named to tell what is the actual condition - for example when waiting for a GPIO connected hardware button:
button_pressed = False
while not button_pressed:
    # do something
    # do something more
    button_pressed = read_GPIO_button_press()
And so on... Obviously these are no longer that infinite loops, but well, that's how the question was posed originally ;)

Tuesday, 5 February 2013

Coding Gold Dust: How to write an infinite loop in Python

One of the coding style issues that has come up more than often on the Raspberry Pi forum is: how to write an infinite loop in Python?

For obvious reasons, many RPi examples are about hardware or network interfacing, and often these examples are derived from C language code. Interfacing, due to it's event-driven nature (especially when reading something), warrants the use of an infinite loop - or well, an event-loop to be more precise.

In plain C, there is no boolean data type but instead anything 'non zero' evaluates to 'true'. Hence an infinite loop in C is typically (and rightfully so) implemented as a while loop like this:
while (1) {
    printf("Hello, world!\n");
}

It seems that this does work in Python as well:
while 1:
    print "Hello, world!"

By definition a while loop continues execution as long as the condition evaluates to true. So practically any expression that evaluates to true could be used:
while (1 == 1):
    ...
test = "true"
while (test == "true"):
    ...
while (1 < 2):
    ...
However, it should be obvious that these are neither beautiful, explicit, simple, readable nor obvious - which are what 'The Zen of Python' lists as 'guiding design principles' for Python, and could be taken as guiding principles for any Python code. In addition, especially the string comparison might incur a performance hit.

Many programming languages do define proper boolean types. For example Java has a data type called boolean and defines the values true and false for that type. Hence our loop in Java would be:
while (true) {
    System.out.println("Hello, world!");
}
Python too defines a class bool, which can have two values True and False. And because there is a boolean data type, it should make perfect sense to use that and (for consistency) only that to implement an infinite loop:
while True:
    print "Hello, world!"
I rest my case ;)

In addition to The Zen of Python, there is a Python Style Guide available - definitely worth a read.

P.S. Thanks for fellow RPI forum user alexeames for the idea of 'Gold Dust' :)