3 ms·
> Python being a dynamically typed, interpreted language 'CPython' is the defining implementation of the dynamically typed language 'Python' using a byte-code
by lispm 9y ago
> Python being a dynamically typed, interpreted language
'CPython' is the defining implementation of the dynamically typed language 'Python' using a byte-code VM (and no jit compiler).
bash-3.2$ time /tmp/bench.py
5000000050000000
real 0m19.763s
user 0m15.015s
sys 0m4.309s
'SBCL' is an implementation of the dynamically typed language 'Common Lisp' using a native code compiler.
bash-3.2$ time /tmp/bench.lisp
5000000050000000
real 0m0.319s
user 0m0.294s
sys 0m0.017s
The unoptimized code is roughly 65 times faster in SBCL compared to CPython - including startup time.
- exikyut 9y agoThis is an unreproducible benchmark. Can we have the programs you used?
- lispm 9y agoSee the comments in the original article for the python examples... The Lisp program is basically this: (format t "~a~%" (loop for i from 1 upto 100000000 sum i)) The Python code can be made a lot faster by using xrange and also reduce. But then the SBCL compiler can optimize a type declared version down to 0.07 seconds runtime for the script. (locally (declare (optimize (speed 3) (debug 0) (safety 0))) (format t "~a~%" (loop for i fixnum from 1 upto 100000000 sum i of-type fixnum)))
- acdha 9y ago> The Python code can be made a lot faster by using xrange and also reduce. This is a key distinction since it reveals that most of the difference is due to these programs doing different things. Changing this to compare the same thing shows why this matters: cadams@jupiter:~ $ sbcl --version SBCL 1.4.0 cadams@jupiter:~ $ python2.7 --version Python 2.7.14 cadams@jupiter:~ $ pypy --version Python 2.7.13 (84a2f3e6a7f88f2fe698e473998755b3bd1a12e2, Oct 05 2017, 16:34:13) [PyPy 5.9.0 with GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)] cadams@jupiter:~ $ time ./test.lisp 5000000050000000 real 0m0.209s user 0m0.194s sys 0m0.011s cadams@jupiter:~ $ time python2.7 test.py 5000000050000000 real 0m0.758s user 0m0.744s sys 0m0.008s cadams@jupiter:~ $ time pypy test.py 5000000050000000 real 0m0.123s user 0m0.101s sys 0m0.019s So at the end of that we've discovered two things we already knew: an interpreter is slower than a JIT given enough work to balance the startup time, and that allocating a list with millions of items and then immediately discarding it is more expensive than summing an iterator. Since Python 3 made range() lazy by default, the core developers clearly agree that this is better than allocating lists unless explicitly requested.
- kuwze 9y agoYeah, I've never understood that. When I was quite the neophyte I thought interpreted languages couldn't be compiled, and then Common Lisp enlightened me.