pointless musings on performance

M

mk

#!/usr/local/bin/python

import timeit


def pythonic():
nonevar = None
zerovar = 0
for x in range(1000000):
if nonevar:
pass
if zerovar:
pass

def unpythonic():
nonevar = None
zerovar = 0
for x in range(1000000):
if nonevar is not None:
pass
if zerovar > 0:
pass

for f in [pythonic, unpythonic]:
print f.func_name, timeit.timeit(f, number=10)



# ./t.py
pythonic 2.13092803955
unpythonic 2.82064604759

Decidedly counterintuitive: are there special optimizations for "if
nonevar:" type of statements in cpython implementation?


regards,
mk
 
C

Chris Rebert

mk wrote in in
comp.lang.python:



from dis import dis

dis( unpythonic )

18          31 LOAD_FAST                0 (nonevar)
            34 LOAD_CONST               0 (None)
            37 COMPARE_OP               9 (is not)
            40 JUMP_IF_FALSE            4 (to 47)

dis( pythonic )

11          31 LOAD_FAST                0 (nonevar)
            34 JUMP_IF_FALSE            4 (to 41)

In other words, CPython doesn't happen to optimize `if nonevar is not
None` as much as it theoretically could (which would essentially
require a JUMP_IF_NONE opcode). Since CPython isn't known for doing
fancy optimizations, this isn't surprising.

Cheers,
Chris
 
T

Terry Reedy

Chris said:
In other words, CPython doesn't happen to optimize `if nonevar is not
None` as much as it theoretically could (which would essentially
require a JUMP_IF_NONE opcode). Since CPython isn't known for doing
fancy optimizations, this isn't surprising.

There is a limit of 256 bytecodes. I believe there are currently fewer.
It would seem that adding bytecodes that combine current pairs would
speed the interpreter, depending on how often the combined pair is used.
And people have looked for frequent pairs across a corpus of code, and
proposed additions.

However, additional bytecodes enlarge the basic bytecode eval loop,
possibly (and sometimes actually) leading to to more processor cache
misses and slower execution. At least some proposed non-essential
additions have been rejected for the reason.

Also, even though CPython-specific bytecodes are outside the language
definition, and could theoretically be revamped every minor (x.y)
release, there is a cost to change. Rewrite the ast to bytecode
compiler, rewrite dis, rewrite the dis doc, and burden anyone concerned
with multiple versions to remember. So in practice, change is minimized
and unassigned bytecodes are left open for the future.

Optimizations that make better use of a fix set of bytecodes are a
different topic. Guido is conservative because historically, compilier
optimizations are too often not exactly equivalent to naive, obviously
correct code in some overlooked corner case, leading to subtle,
occasional bugs. Of course, byte code changes could mess-up current
optimizations that are performed.

Terry Jan Reedy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top