public
Last active

Hython Runtime

  • Download Gist
info.md
Markdown

tl;dr

PyPy is ruddy fast. So is Hy.

Time of fib(9), using a simple recursive implementation.

cPython 2.6 cPython 2.7 PyPy cPython 3.2
Native 11.81 seconds 9.12 seconds 1.06 seconds 11.74 seconds
Hython 16.92 seconds 11.63 seconds 2.72 seconds 11.02 seconds
Clojure-py 302.52 seconds 242.64 seconds 11.49 seconds (can't run)

How the tests were preformed

The following tests some iteration over the following functions:

Hython (hython.hy):

(defn fibhy [x]
    (if (<= x 2)
      x
    (+ (fibhy (- x 2)) (fibhy (- x 1)))))

Clojure-py (cloj.clj):

(ns cloj)
(defn fibclj [x]
  (if (<= x 2)
    x
    (+ (fibclj (- x 2)) (fibclj (- x 1)))))

Native (builtin)

def nfib(x):
    if x <= 2:
        return x
    return nfib(x - 2) + nfib(x - 1)

And, the foo.py script:

#!/usr/bin/env python
import hy.lang.importer
from hython import fibhy
import clojure.main
from cloj import fibclj


if __name__ == '__main__':
    import sys
    import timeit
    print "Testing fib of 9, bunch of times."
    print ""
    print "Native impl", timeit.timeit("nfib(9)", setup="from __main__ import nfib")
    print "Hython impl", timeit.timeit("fibhy(9)", setup="from __main__ import fibhy")
    print "Clojure-py impl", timeit.timeit("fibclj(9)", setup="from __main__ import fibclj")

Results

PyPy 1.9.0

Version:

Python 2.7.2 (1.9+dfsg-2, Jul 13 2012, 03:57:27)
[PyPy 1.9.0 with GCC 4.7.1]

Output:

Testing fib of 9, bunch of times.

Native impl 1.06238484383
Hython impl 2.72712397575
Clojure-py impl 11.4938201904

cPython 2.7

Version:

Python 2.7.3

Output:

Testing fib of 9, bunch of times.

Native impl 9.12584590912
Hython impl 11.6347429752
Clojure-py impl 242.644510984

cPython 2.6

Version:

Python 2.6.8

Output:

Testing fib of 9, bunch of times.

Native impl 11.8195121288
Hython impl 16.9216940403
Clojure-py impl 302.52679801

cPython 3.2

Version:

Python 3.2.3

Output:

Native impl 11.746108055114746
Hython impl 11.024507999420166

For reference: Native C version takes just 0.105 seconds. Well, or 0.3 seconds if you include compiling:

nfib.c:

int nfib(int x) {
    if (x <= 2)
        return x;

    return nfib(x - 2) + nfib(x - 1);
}

foo.c:

#include <stdio.h>
#include <sys/time.h>

int nfib(int x);

static double seconds(const struct timeval *const t) {
        return t->tv_sec + t->tv_usec * 1e-6;
}

int main() {
        struct timeval t1, t2;
        int i;

        gettimeofday (&t1, NULL);

        for (i = 0; i < 1000000; ++i)
                nfib(9);

        gettimeofday (&t2, NULL);

        printf("%.3f s\n", seconds(&t2) - seconds(&t1));

        return 0;
}

Benchmarked like this: time ( gcc -O3 -Wall -Werror nfib.c foo.c -o nfib && ./nfib )

@hasselmm - nice baseline, thanks!

Well, if we're sharing reference points, here's another. 0.0016s, or 0.125s if we're including compilation.

import Data.Time

fib n | n < 2 = 1
      | otherwise = fib (n - 1) + fib (n - 2)

measure x = do
    a <- getCurrentTime
    x
    b <- getCurrentTime
    return $ b `diffUTCTime` a

main = print =<< (measure $ sequence_ $ replicate 1000000 $ return $ fib 9)
$ time (ghc --make -O2 fib && ./fib)
0.001671s
( ghc --make -O2 fib && ./fib; )  0.10s user 0.01s system 92% cpu 0.125 total

Update: I guess we don't need to make any binaries or that -O2 stuff.

$ time (runhaskell fib.hs)
0.001671s
( runhaskell fib.hs; )  0.22s user 0.04s system 97% cpu 0.261 total

Sweet, thanks @malbork !

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.