
How slow is Python really? Or how fast is your language? - kisamoto
http://codegolf.stackexchange.com/questions/26323/how-slow-is-python-really-or-how-fast-is-your-language
======
wting
Python is fast enough, until it isn't and then there are no simple
alternatives.

If your problem is numerical in nature, you can call popular C modules (numpy,
etc) or write your own.

If your functions and data are pickleable, you can use multiprocessing but run
into Amdahl's Law.

Maybe you try Celery / Gearman introducing IO bottlenecks transferring data to
workers.

Otherwise you might end up with PyPy (poor CPython extension module support)
and still restricted by the GIL. Or you'll try Cython, a bastard of C and
Python.

Python has been my primary language the past few years and it's great for
exploratory coding, prototypes, or smaller projects. However it's starting to
lose some of the charm. Julia is filling in as a great substitute for
scientific coding in a single language stack, and Go / Rust / Haskell for the
other stuff. I've switched back to the static language camp after working in a
multi-MLOC Python codebase.

~~~
oblique63
> _Julia is filling in as a great substitute for scientific coding in a single
> language stack, and Go / Rust / Haskell for the other stuff._

I've been wondering about why so many python devs have migrated to using Go
recently instead of Julia, given that Julia is a lot closer to python and has
performed as good as, if not better than, Go in some benchmarks [1]. Granted
I've really only toyed with Julia and Go a few times as I've never really
needed the performance much myself, but I'm curious about your preference of
Go/Rust over Julia for "the other stuff".

What would you say makes Julia less suitable (or Go more suitable) for
nonscientific applications? Is it just the community/support aspect? Cause
that seems like an easy tide to overturn by simply raising more awareness
about it (we see Go/Rust/Haskell blog posts on the front page of HN every
week, but not too many Julia posts).

Just curious cause I'm not nearly experienced enough with any of these young
languages yet to know any better, and have only recently started to consider
taking at least one of them up more seriously.

[1] [http://julialang.org/benchmarks/](http://julialang.org/benchmarks/)

~~~
wting
Static typing is a boon when refactoring large codebases, even with >90% test
coverage.

I'm migrating an in house ORM to SQLAlchemy. Lack of compiler support and/or
static code analysis makes the transition more difficult than it needs to be.

Dynamic typing allows one to defer error handling to the future, essentially
creating technical debt for the sake of developer speed and convenience. For
many use cases this is an acceptable trade off.

However as a codebase grows in complexity, it's better to handle errors as
early as possible since the cost of fixing an error grows exponentially the
farther it is from the developer (costs in ascending order: editor < compiler
< testing < code review < production).

~~~
igouy
Tools matter:

 _A very large Smalltalk application was developed at Cargill to support the
operation of grain elevators and the associated commodity trading activities.
The Smalltalk client application has 385 windows and over 5,000 classes. About
2,000 classes in this application interacted with an early (circa 1993) data
access framework. The framework dynamically performed a mapping of object
attributes to data table columns.

Analysis showed that although dynamic look up consumed 40% of the client
execution time, it was unnecessary.

A new data layer interface was developed that required the business class to
provide the object attribute to column mapping in an explicitly coded method.
Testing showed that this interface was orders of magnitude faster. The issue
was how to change the 2,100 business class users of the data layer.

A large application under development cannot freeze code while a
transformation of an interface is constructed and tested. We had to construct
and test the transformations in a parallel branch of the code repository from
the main development stream. When the transformation was fully tested, then it
was applied to the main code stream in a single operation.

Less than 35 bugs were found in the 17,100 changes. All of the bugs were
quickly resolved in a three-week period.

If the changes were done manually we estimate that it would have taken 8,500
hours, compared with 235 hours to develop the transformation rules.

The task was completed in 3% of the expected time by using Rewrite Rules. This
is an improvement by a factor of 36._

from “Transformation of an application data layer” Will Loew-Blosser OOPSLA
2002

[http://portal.acm.org/citation.cfm?id=604258](http://portal.acm.org/citation.cfm?id=604258)

------
Wilya
Using a Numpy-based program as an example of how Python can be fast is a bit
strange.

It shows that Python can be fast enough _if you leave the heavy computational
parts to libraries written in other languages_. Which is interesting, but
doesn't say much about the speed of Python itself.

~~~
pekk
It isn't strange, it's standard practice. What would be strange is to force
Python to hold one hand behind its back and be used in a totally unrealistic
way that doesn't reflect normal practice. And by strange I mean basically
dishonest about the performance available when using Python.

~~~
stefantalpalaru
> the performance available when using Python

The honest thing would be to say "yes, Python is slow, but you can use some
fast modules written in C".

You can even go farther and say that if you're going to use Python for non-
trivial projects you better learn C (or some C generator like Cython).

~~~
calpaterson
You only need to know C to get fast Python code for a tiny minority of
situations. For one, most interesting C wrappers have already been written and
second, the majority of C code you will use in normal business software
contexts isn't used by FFI.

For a normal web application the request flow goes something like: nginx
(WSGI) -> uwsgi -> web application code -> psycopg2 driver -> postgres. Only
the web application part is written in Python, so for practical purposes you
actually have a C stack that uses Python for business logic. Loads of
libraries, from json parsers to templating libraries include optional C code
for speedups.

~~~
stefantalpalaru
Guess where the bottleneck is when you need to generate a dynamic page for
each and every request.

~~~
calpaterson
In the database? About 90% of bottlenecks boil down to something along the
lines of "this query is slow" or "there are a lot of queries here". This has
been true since the dotcom boom

~~~
stefantalpalaru
Guess again. All these benchmarks use the same database:
[http://www.techempower.com/benchmarks/#section=data-r8&hw=i7...](http://www.techempower.com/benchmarks/#section=data-r8&hw=i7&test=query)

~~~
reitzensteinm
The real answer is "it depends".

The whole rise of memcached and NoSQL should pretty clearly indicate that many
developers are finding their database to be the bottleneck.

There's much less of a push for high performance languages, even though there
are many that are also quite nice to work with (eg, Clojure). Since this is a
Python discussion, searching for "Django PyPy" and "Django NoSQL" should be
instructive.

You're combining a false dichotomy with snark, which really shouldn't have a
place here on HN.

~~~
calpaterson
Well, at least some of the NoSQL movement was some people preferred to model
data as documents or dictionaries or graph, etc instead of relations

------
moe
Anecdotical datapoint: For a great many years I used to consider python a very
slow language. Then I switched to Ruby and realized how slow a language can
_really_ be and yet still be practical for many use-cases.

~~~
Freaky
Except Ruby isn't really significantly slower than Python?

~~~
dragonwriter
The mainline implementations are not that far apart _now_ , but IIRC it wasn't
all that long ago that MRI was significantly slower than CPython.

~~~
Freaky
I suppose it depends on how you define "that long ago" and "mainline
implementations". From my point of view it's coming along to about half a
decade, but I guess 1.8's remained popular in many places as recently as 2-3
years ago.

~~~
moe
The difference does not primarily stem from raw interpreter performance but
rather from the different community mindsets and resulting ecosystems.

The average code-quality in rubygems is just not very high. Consequently most
libraries are completely oblivious to performance aspects.

This reaches straight into the core infrastructure (rubygems, bundler) and all
major projects (Rails). Leading to the simple fact that Ruby loses out on many
practical benchmarks _before your script has even loaded_.

Likewise the synergies of less than bright behaviors from all the gems in your
average Rails project (and no least Rails itself) do indeed make the
performance gap towards an average django project _much_ larger than the mere
difference in sheer interpreter performance.

That's all not meant to bash Ruby anyway. It's a trade-off me and many others
are willing to make, for the convenience that ruby provides _after_ it has
finally set its fat belly into motion.

But let's not pretend these differences don't exist when everyone who has ever
used both languages knows them all to well.

------
lamby
Obviously, this is a silly benchmark and we should stop giving it any credit.

However, even "real world" anecdotes in this area can be a minefield.

Take, for example, an existing Python application that's slow which requires a
rewrite to fix fundamental architectural changes.

Because you feel you don't need necessarily need the flexibility of Python the
second time around (as you've moved out of the experimental or exploratory
phase of development), you decide to rewrite it in, say, Go, or D or
$whatever.

The finished result turns out to be 100X faster—which is great!—but the danger
is always there that you internalise or condense that as "lamby rewrote Python
system X in Go and it was 100X faster!"

------
chrisBob
I spend a lot of time debating program speed (mostly C vs MATLAB), but the
problem is that the programming and compile time usually makes more of a
difference than people consider.

If my C is 1000x faster and saves me 60 seconds every time I run the program,
but takes an extra 2 days to write initially, and the program is seeing lots
of edits meaning that on average I have to wait 2 minutes for it to compile
then I am MUCH better off with the _slower_ MATLAB until I am running the same
thing a few thousand times.

Plus there is the fact that I can look at HN while a slightly slower program
is running, so I win both ways.

~~~
jerf
I think a lot of that delta is going to prove to have been an accident of
history, though. In the past 10-15 years, we've had a lot of "dynamic"
languages, which have hit a major speed limit (see another comment I made in
this discussion about how languages really do seem to have implementation
speed limits). Using a "dynamic" language from the 1990s has been easier than
using gussied-up static 1970s tech for a quick prototype, but what if the real
difference has more to do with the fact that the 1990s tech simply has more
experience behind the design, rather than an inherent ease-of-use advantage?

It's not hard to imagine a world where you instead use Haskell, prototyping
your code in GHCi or even just writing it in Haskell directly, pay a minimal
speed penalty for development since you're not being forced to use a klunky
type system, and get compiled speeds or even GPGPU execution straight out of
the box. (And before anyone freaks out about Haskell, using it for numeric
computations requires pretty much zero knowledge about anything exotic... it's
pretty straightforward.) It's not out of the question that using Haskell in
this way would prototype even faster than a dynamic language, because when it
gives you a type error at compile time rather than at runtime, or worse,
running a nonsense computation that you only discover afterwards was nonsense,
you could save a lot of time.

I don't think there has to be an inherent penalty to develop with native-speed
tech... I think it's just how history went.

~~~
rdtsc
> In the past 10-15 years, we've had a lot of "dynamic" languages, which have
> hit a major speed limit

Exactly. I think that is correlated very well with single core CPU speedups.

Remember when Python was rising the fastest, single core CPU speed was also
pretty much doubling every year. SMP machines were exotic beasts for most
developers back then.

So just waiting for 2-3 years you got very nice speedup and Python ran
correspondingly faster (and fast enough!).

Then we started to see multiple cores, hyperthreads, and so on. That is when
talk about the GIL started. Before that nobody cared about the GIL much. But
at some point, it was all GIL,GIL,GIL.

> It's not hard to imagine a world where you instead use Haskell

Hmm interesting. I wonder if that approach is ever taken in a curriculum.
Teach kids to start with Haskell. It would be interesting.

~~~
jerf
I share that theory. Part of what led me down this road was when I
metaphorically looked around about two years ago and realized my code wasn't
speeding up anymore. Prior to that I'd never deeply thought about the
"language implementation speed is not language speed" dogma line, but just
accepted the sophomoric party line.

"Hmm interesting. I wonder if that approach is ever taken in a curriculum.
Teach kids to start with Haskell. It would be interesting."

To be clear, I was explicitly discussing the "heavy-duty numerical
computation" case, where typing as strong as Haskell's isn't even that hard.
Learn some magic incantations for loading and saving data, and it would be
easy to concentrate on just the manipulations.

But yes, people have done this and anecdotally report significant success. The
Google search "Haskell children" (no quotes in the real search) comes up with
what I know about, so I'll include that in this post by reference. It provides
support for the theory that Haskell is not _that_ intrinsically hard, it's
just so _foreign_ to what people know. If you don't start out knowing
anything, it's not that weird.

------
ahoge
Numpy is written in C. That's why it's fast.

Better:
[http://benchmarksgame.alioth.debian.org/](http://benchmarksgame.alioth.debian.org/)

~~~
wffurr
You didn't read the thread. The OPs code used very small arrays and using
numpy was slowing the code down by an order of magnitude. The pure python
solution is 17x faster.

~~~
TillE
It's really important to remember that the interface of a VM can be one of the
slowest parts. When your LuaJIT code is making a ton of calls to tiny C
functions, it's gaining hardly any benefit from the JIT.

~~~
awj
Yeah, things like marshaling data across the interface barrier, or chasing the
pointer indirections inherent in calling functions, can have a significant
cost. Usually it isn't significant _enough_ , but as always the devil is in
the details.

------
fmdud
_Holy false comparison, Batman!_

Why would you use Numpy for arrays that small? Oh, looks like someone actually
just wrote it in CPython, no Numpy, and it clocked in at 0.283s. Which is
fine. It's Python.

This thread reminds me of the scene in RoboCop where Peter Weller gets shot to
pieces. Peter Weller is Python and the criminals are the other languages.

------
Igglyboo
Judging by the top submission being also written in python, I think this just
shows how unoptimized OP's original code was rather than how slow the language
is.

Not that python is fast, it isn't. And using numpy seems a bit disingenuous
anyways "Oh my python program is faster because I use a library that's 95% C"

------
jzwinck
The same author previously posted this code as a question on Stack Overflow:
[http://stackoverflow.com/questions/23295642/](http://stackoverflow.com/questions/23295642/)
(but we didn't speed it up nearly as much as the Code Golf champions).

If you enjoyed this Python optimization, you may also enjoy:
[http://stackoverflow.com/questions/17529342/](http://stackoverflow.com/questions/17529342/)

This sort of thing comes up a lot: people write mathematical code which is
gratuitously inefficient, very often simply because they use a lot of loops,
repeated computations, and improper data structures. So pretty much the same
as any other language, plus the extra subtlety of knowing how and why to use
NumPy (as it turned out, this was not a good time for it, though that was not
obvious).

------
jules
You can make this far faster by changing the data representation. You can
represent S as a bit string so that if the i'th bit is 0 then S[i] = 1 and if
the i'th bit is 1 then S[i] = -1. Lets call that bit string A. You can
represent F as two bit strings B,C. If the i'th bit in B is 0 then F[i] = 0.
If the i'th bit of B is 1 then if the i'th bit of C is 0 then F[i] = 1 else
F[i] = -1. Now the whole thing can be expressed as parity((A & B) ^ C). The
parity of a bit string can be computed efficiently with bit twiddling as well.
Now the entire computation is in registers, no arrays required. The random
generation is also much simpler, since we only need to generate random bit
strings B,C and this is already directly what random generators give us. I
wouldn't be surprised if this is 1000x faster than his Python.

------
alexchamberlain
It's really fast to develop in, and with NumPy/Pandas/Scipy it runs numerical
models fairly fast too. You do have to spend time getting to know `cProfile`
and `pstats`; saved over 80% on runtime of something the other day.

------
pjmlp
What should the OP ask instead:

"How fast is the code produced by your compiler."

I keep seeing this misconception about languages vs implementations.

EDIT: Clarified what my original remark meant.

~~~
jerf
I no longer accept the idea that languages don't have speeds. Languages place
an upper bound on realistic speed. If this isn't true in theory, it certainly
is true in practice. Python will forever be slower than C. If nothing else,
any hypothetical Python implementation that blows the socks off of PyPy must
still be executing code to verify that the fast paths are still valid and that
nobody has added an unexpected method override to a particular object or
something, which is an example of something in Python that makes it
fundamentally slower than a language that does not permit that sort of thing.

The "misconception" may be the casual assumption that the runtimes we have
today are necessarily the optimal runtimes, which is not generally true. But
after the past 5-10 years, in which _enormous_ amounts of effort have been
poured into salvaging our "dynamic" language's (Python, JS, etc.) run speeds,
which has pretty much resulted in them flatlining around ~5 times slower than
C with what strikes me as little realistic prospect of getting much lower than
that, it's really getting time to admit that language design decisions do in
fact impact the ultimate speed a language will be capable of running at. (For
an example in the opposite direction, see LuaJIT, a "dynamic" language that
due to careful design can often run at near-C.)

(BTW, before someone jumps in, no, current Javascript VMs do _NOT_ run at
speeds comparable to C. This is a common misconception. On trivial code that
manipulates numbers only you can get a particular benchmark to run at C
speeds, but no current JS VM runs at C speeds _in general_ , nor really comes
even close. That's why we need asm.js... if JS VMs were already at C speeds
you wouldn't be able to get such speed improvements from asm.js.)

~~~
pjmlp
It is always a matter of ROI, how far one is willing to invest, money and
time, in a compiler/interpreter/JIT implementation for the use cases a
language is targeted for.

As for the current state of native compilers for dynamic languages, they
suffer from the fact that past the Smalltalk/Lisp Machines days, very little
focus has given to them in the industry.

Hence little money for research, while optimizing compilers for static typed
languages where getting improved.

Dylan was the last dynamic language with a AOT compiler targeted to the
industry as system programming language, before being canceled by Apple.

If it wasn't for the JavaScript JIT wars, probably the situation of compilers
for dynamic languages would be much worse.

~~~
lispm
Lisp Machines never had sophisticated compilers. The compilers for the Lisp
Machines were primitive in their capabilities. The compiled to a mostly stack
architecture, where some speed was recovered in hardware from generic
instructions. The work on better compilers for Lisp came most from other
places: CMU for their Unix-based CMUCL, Franz with Allegro CL, Harlequin with
LispWorks, Lucid had a very good compiler with Lucid CL, Dylan at Apple for
early ARM, CLICC in Germany, SBCL as a clean up of CMUCL, Scieneer CL as a
multi-core version of CMUCL, mocl as a version of CLICC for iOS/Android, ...
plus a few special purpose compilers...

Once you add sophisticated compilation, dynamic languages implementations are
no longer 'dynamic'.

This topic is pretty much solved for Lisp. On one extreme we have fully
dynamic interpreters + then dynamic AOT compiler based ones. For delivery
there are static delivery modes available (for example with treeshakers as in
LispWorks).

On the extreme side you get full program compilers like Stalin (for a subset
of Scheme) or like mocl (a recent compiler for a static subset of Common Lisp,
for iOS and Android).

------
donniezazen
As a new programmer with only Java(Android) under my arms, I find the whole
concept of "your language" mind boggling.

~~~
Roboprog
See:

[http://www.catb.org/jargon/html/L/languages-of-
choice.html](http://www.catb.org/jargon/html/L/languages-of-choice.html)

and

[http://www.catb.org/jargon/html/T/TMTOWTDI.html](http://www.catb.org/jargon/html/T/TMTOWTDI.html)

------
taude
Go/Scala, etc. programmers, go add your answer to the OPs S.E. answer. Lots of
other entertaining coding examples there.

------
WoodenChair
Summary: Question asker wrote a program in Python using numpy (A Python
library that calls C code) which could've been more performant if written in
pure Python (something to do with array sizes being used) and Python in
general is slower than C/C++/Fortran/Rust. Anything else new?

~~~
igouy
What's new is that StackExchange has a "Programming Puzzles & Code Golf beta".

~~~
yahelc
Not really new, at least not in internet time. It's been around for at least 3
years.

------
malkia
Python is slow, but handy for automation.

------
chrismorgan
Yet another attempt at a comparison scuttled by using randomness.

Different things use different types of randomness. Some are fast. Some are
slow. If your comparison is not using the same type of randomness, that
comparison is comparatively useless.

~~~
dbaupp
It's not being scuttled by randomness, since the times are so wildly
different; my measurements of my Rust code indicate "only" 20% of the time is
being spend in the RNG ranging up to 35% if I use StdRng rather than
XorShiftRng, this difference is peanuts compared to the 750× (not percent)
speed-ups the Fortran/Rust/C/C++ sees over the original Python (and even
compared to the 30× speed-up seen over the optimised Python).

~~~
chrismorgan
OK, I retract the word "scuttled". But the comparison is still meaningfully
damaged by it once you get to closer comparisons, say between two of the top
performers.

