metaclasses and performance

M

Mirko Dziadzka

Hi all

I'm playing around with metaclasses and noticed, that there is small
but mesurable a performance difference in the code shown below. With a
more complex example I get a 5 percent performance penalty for using a
metaclass. Until today I assumed, that a metaclass has no performance
impact at all after class creation.
Can someone explain me the performance difference between the two classes
test1 and test2

Thank's in advance

Mirko

---- cut here -----

class meta(type):
pass

class test1(object):
__metaclass__ = meta # using type via meta here
def __init__(self):
self.foo = 42
def get_foo(self):
return self.foo

class test2(object):
__metaclass__ = type # using type directly
def __init__(self):
self.foo = 42
def get_foo(self):
return self.foo

# and here the performance test code ... it's only 2% on my machine
import time
for c in [test1, test2] * 10:
t = c()
start = time.time()
for i in xrange(10 * 1000 * 1000):
t.get_foo()
print c.__name__, time.time() - start

---- cut here -----
 
L

Lenard Lindstrom

Mirko said:
Hi all

I'm playing around with metaclasses and noticed, that there is small
but mesurable a performance difference in the code shown below. With a
more complex example I get a 5 percent performance penalty for using a
metaclass. Until today I assumed, that a metaclass has no performance
impact at all after class creation.
Can someone explain me the performance difference between the two classes
test1 and test2

Thank's in advance

Mirko

---- cut here -----

class meta(type):
pass

class test1(object):
__metaclass__ = meta # using type via meta here
def __init__(self):
self.foo = 42
def get_foo(self):
return self.foo

class test2(object):
__metaclass__ = type # using type directly
def __init__(self):
self.foo = 42
def get_foo(self):
return self.foo

# and here the performance test code ... it's only 2% on my machine
import time
for c in [test1, test2] * 10:
t = c()
start = time.time()
for i in xrange(10 * 1000 * 1000):
t.get_foo()
print c.__name__, time.time() - start

---- cut here -----

I don't know if C asserts are active in release Python, but for
new-style classes one thing that happens during attribute lookup is that
an object's class is asserted to be an instance of type. Class test2
immediately passes the test since its type is "type". But test1's type
is meta, so a function is called to check that meta is a subclass of
"type". This may be the cause of the slowdown. Otherwise attribute
lookups for test1 and test2 instances are identical.
 
M

Mirko Dziadzka

Lenard Lindstrom said:
I don't know if C asserts are active in release Python, but for
new-style classes one thing that happens during attribute lookup is that
an object's class is asserted to be an instance of type.

Thank's for the explanation. My Linux distribution does not set NDEBUG
when compiling the python package so asserts are still in place. A self
compiled python does not use the asserts and is 20% faster in my micro
benchmark.

Mirko
 

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,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top