Profiling Maya's python interfaces

One of the common points I hear against PyMel as an interface to the Maya API is its speed. The python 2.0 API is reportedly much faster. I was curious about how much faster, and wanted to see some numbers, using python's timeit module.

import maya.standalone as msa
msa.initialize()

import timeit

om_setup = """
from maya.api import OpenMaya as om
import random
rand_mtx = lambda: om.MMatrix([random.random() for _ in xrange(16)])
"""

pmc_setup = """
import pymel.core as pmc
import random
rand_mtx = lambda: pmc.dt.Matrix([random.random() for _ in xrange(16)])
"""

omt = timeit.timeit("rand_mtx() * rand_mtx()", setup=om_setup, number=1000)
pmct = timeit.timeit("rand_mtx() * rand_mtx()", setup=pmc_setup, number=1000)
print("OM with construction:\n{}".format(omt))
print("PyMel with construction:\n{}".format(pmct))
print("OM is {} times faster than pymel, with matrix construction.".format(pmct/omt))

This script only records the time taken to perform matrix multiplication. But as matrix multiplication is a very common task for me, can be expensive, and is a fairly foundational aspect of any 3D package, I figured it would make a decent benchmark for me.

When I run on my laptop, I record PyMel taking approximately 600 times as long to perform 1,000 matrix multiplications - almost ten full seconds.I was curious to further isolate the multiply operation itself, though, and decided to try it after moving the matrix constructors into the setup code:

# now try with pre-constructed matrices, just use the same one
oms_setup = """
from maya.api import OpenMaya as om
import random
mtx = om.MMatrix([random.random() for _ in xrange(16)])
"""

pmcs_setup = """
import pymel.core as pmc
import random
mtx = pmc.dt.Matrix([random.random() for _ in xrange(16)])
"""

omst = timeit.timeit("mtx * mtx", setup=oms_setup, number=1000)
pmcst = timeit.timeit("mtx * mtx", setup=pmcs_setup, number=1000)
print("OM static:\n{}".format(omst))
print("PyMel static:\n{}".format(pmcst))
print("OM is {} times faster than pymel with matrix multiplcation only.".format(pmcst/omst))

Contrary to my expectations, this made PyMel even slower (relative to OpenMaya) - taking over 5,500 times as long to perform just the multiplication! Here are my raw numbers:

OM with construction:
0.0156702088991
PyMel with construction:
8.84449015373
OM is 564.414310665 times faster than pymel, with matrix construction.
OM static:
0.000348093822831
PyMel static:
1.95670422716
OM is 5621.1977887 times faster than pymel with matrix multiplcation only.

It would be interesting to see how the numbers compare when testing different operations head-to-head like this.