[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] 2D vector class



Brian Fisher wrote:
> I love vector classes with operator overloading... I couldn't stand to
> code without them (even though in python, it means there's probably a
> lot of object allocation and function calls for simple vector math,
> wasting performance). Code is just so much shorter & more readable
> with them. I know that I pay for it in performance to use them, and I
> know the one I use isn't the best performing one... I'll just wait to
> care about that when it's a real problem.

I did some back-of-the-envelope benchmarking of various
implementations of Vector operations. Attached is the program that I
used. My findings were:

- Numeric is faster than map is faster than a list comprehension
- explicitly storing two variables is even faster (not shown)
- using functions from the operator module is faster than built-in
math operators
- tuples seem to be a little faster to iterate over than lists

And some vector-unrelated findings:

- function calls are faster than method calls
- accessing a bound method is slower than accessing an instance variable

In benchmarking my game, I found that I was creating a *lot* of new
vector objects, and this does things to your performance. For this
reason my vectors are not immutable, but take advantage of in-place
operations to conserve objects.

I found that it was rare that I needed to access individual elements
of a vector, but implemented __iter__ by returning iter([x, y]). This
was "good enough" and pretty straightforward.

Ethan
s = '''from operator import sub
def add1(v1, v2):
    return [a + b for (a, b) in zip(v1, v2)]

def sub1(v1, v2):
    return [a - b for (a, b) in zip(v1, v2)]

def sub2(v1, v2):
    return [sub(a,b) for (a, b) in zip(v1, v2)]

def sub3(v1, v2):
    return map(sub, v1, v2)
v1a = [4.2, 5.4]
v1b = [12.0, -4.1]

v2a = (4.2, 5.4)
v2b = (12.0, -4.1)'''

import timeit

t = timeit.Timer()
print 'baseline', t.repeat()
for i in ['sub1', 'sub2', 'sub3']:
    for j in [1, 2]:
        t = timeit.Timer('a = %s(v%da,v%db)'%(i,j,j), s)
        print i, j, t.repeat()

s2 = '''import Numeric
def sub4(v1, v2):
    return Numeric.subtract(v1, v2)

v1a = Numeric.array([4.2, 5.4])
v1b = Numeric.array([12.0, -4.1])'''

t = timeit.Timer('a = sub4(v1a, v1b)', s2)
print 'numeric', t.repeat()



s3 = '''
class C(object):
    x = None
    def __init__(self):
        pass
    def f(self, o2):
        pass
    def g(self):
        pass

def f(o1, o2):
    pass
o1 = C()
o2 = C()'''

for i in ['o1.f(o2)', 'C.f(o1, o2)', 'f(o1, o2)']:
    t = timeit.Timer(i, s3)
    print i, t.repeat()

for i in ['o1.x', 'o1.g', 'o1.g()']:
    t = timeit.Timer(i, s3)
    print i, t.repeat()

Attachment: signature.asc
Description: OpenPGP digital signature