4

I just wrote this code, and I was wondering why it performs significantly worse in Python 3? Is it the same across all platforms? Is this just bad luck, or is Py3 generally slower?

Thanks!

Performance:

       python 2.6  python 3.1  pypy 1.5
linux  2.2s        2.4s        0.8s
os x   2.5s        3.4s        0.7s

Code: (sorry it's so hasty and inefficient!)

import itertools
import random

def fptp_draw(result):
    votes = [prefs[0] for prefs in result]
    counts = [len([v for v in votes if v == c]) for c in [1, 2, 3]]
    s = sorted(counts)
    #print('fptp', counts)
    return s[-1] == s[-2]

def av_remove(prefs, cand):
    if prefs[0] != cand:
        return prefs
    else:
        return prefs[1:]

def av_draw(result):
    nv = len(result)
    cands = [1, 2, 3]
    while True:
        votes = [prefs[0] for prefs in result]
        counts = [len([v for v in votes if v == c]) for c in cands]
        #print('av  ', cands, counts)
        s = sorted(counts)

        if s[-1]*2 > nv:
            return False
        if len(cands) == 2:
            return True

        loser = cands[counts.index(s[0])]
        cands.remove(loser)

        result = [av_remove(prefs, loser) for prefs in result]

    return False

#orders = list(itertools.permutations([1, 2, 3]))
orders = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

#results = list(itertools.product(*itertools.repeat(orders, 6)))
#results = random.sample(results, 5)

def rand_vote():
    return [random.choice(orders) for i in range(1000)]

n = fptp = av = 0
for j in range(1000):
    r = rand_vote()
    #print()
    #print(r)
    n += 1
    if fptp_draw(r):
        fptp += 1
    if av_draw(r):
        av += 1

print(fptp*100.0/n, av*100.0/n)
print(n)
Rodrigo Queiro
  • 1,324
  • 8
  • 15

2 Answers2

4

Py3k is generally slower than python 2.x. That will change as time passes, but the focus for py3k was feature completeness and stability, not speed.

Community
  • 1
  • 1
nmichaels
  • 49,466
  • 12
  • 107
  • 135
  • Thanks - I'm a bit disappointed the hit is so big, but I'm very happy PyPy performs so well, and only required a very small change. – Rodrigo Queiro May 06 '11 at 17:48
1

I think I've answered my own question:

The net result of the 3.0 generalizations is that Python 3.0 runs the pystone benchmark around 10% slower than Python 2.5. Most likely the biggest cause is the removal of special-casing for small integers. There’s room for improvement, but it will happen after 3.0 is released!

EDIT: Although it's surprising that it's a 40% performance hit on OS X...

Rodrigo Queiro
  • 1,324
  • 8
  • 15
  • 2 comments. Firstly, 40% is not that big. Secondly, you're assuming the performance your code tells you how other code will perform. (Although I'm not arguing that 3.1 isn't slower than 2.6.) – Steven Rumbalski May 06 '11 at 19:33