Python/Scripting language performance

Ian Bicking ianb at colorstudy.com
Sat Jun 1 05:08:13 CEST 2002


On Fri, 2002-05-31 at 10:07, Curtis Jensen wrote:
> If Python and Perl are not scripting languages, then what are they?

They are just languages that can be used for scripting.

> Also, is dynamic typing the only reason for python's performance hit? 
> Does this mean that if I use something like Numeric arrays (from the 
> Numeric Module), which pretty much staticaly types it's variables, and 
> define these variables at the top of a function or in the constructor of 
> a class, that I would avoid the performance hit of dynamic typing?  Are 
> there other performance penalties in Python other than dynamic typeing? 
>   What are they?

It's not so much that dynamic typing is the performance hit, as much as
dynamic typing means that many optimizations cannot be made.  In
general, Python does not lend itself to much compile-time optimization
-- for instance, methods in classes can be replaced at runtime, and
classes in modules can be changed as well (since they are just a global
variable).

So not only is the type of a variable or argument dynamic, but once you
know what the type is you don't know exactly how it will respond.

In C++, because of static typing you can often tell exactly what code
will be run when you see something like x.dothis() -- you know the type
(class) of x, and you know the definition of the dothis method.  You can
optimize all sorts of things when you know this.

OTOH, sometimes these optimizations aren't possible -- for instance,
virtual methods in C++ do something very similar to Python method
lookups (though they are still more restricted, and can be optimized
more).  You can also come up with clever optimizations in Python that
utilize the dynamicism for a speed benefit.  For instance:

class Whatever:
  def __init__(self, fancyRepr):
    if fancyRepr:
        self.__repr__ = self.fancyRepr
  def fancyRepr(self):
    return 'one version of repr for the object'
  def __repr__(self):
    return 'the standard repr version'

Then, instead of having a fancyRepr instance variable, and testing it on
each call to __repr__, the logic is contained in the object
instantiation itself.

There's also a certain penalty associated with all of Python's magic
methods -- things like __getattr__, __add__, etc.  This penalty usually
only occurs when you actually use the feature, though, so it's not a big
deal.  But every time you do a dictionary access, there does have to be
a little bit of code to test if you have a real dictionary.


Dynamic typing does not mean optimization is impossible, however.  SELF
pioneered a lot of techniques for doing this kind of optimization, and
that later became JIT in Java.  I think people are talking about doing
JIT stuff in Parrot (the next-generation Perl bytecode interpreter), and
there's also talk of compiling Python into Parrot bytecodes, so that
might come to pass.  Or Python-specific JIT might come to pass.

> I'm still lost on the point of the byte code.  What's the point?  If 
> it's still line by line interpreted, why not just skip the byte code 
> compilation and line by line interpret the source?  Is there some 
> optimization in the byte code?

Byte code is interpreted, but then so is machine code -- *something* has
to be interpreted when the code is run.  Bytecode can't overcome the
dynamic nature of Python, but it does skip a lot of steps in Python --
in particular, you really don't have to parse Bytecode, but it takes
quite a bit of effort to parse Python source code.  Bytecode avoids that
parsing stage.

  Ian







More information about the Python-list mailing list