Friday, 17 August 2012

Performance comparison: MEL vs PyMel vs OpenMaya vs maya.cmds vs C++

Over the years Maya has grown to have quite the myriad of programming APIs. MEL and the C++ API have been joined by Python maya.cmds, the OpenMaya Python API wrapper and PyMel. Now I read Maya 2013 is getting Python API 2.0. I've read a lot of discussion on what's quickest but most of them are based on generic assumptions (simpler is quicker so PyMel must be slowest) and don't quote any specific timings. So I've done some myself, while profiling tools and trying to get the most performance out of them. (All timings are in seconds)
Example: having selected 10000 edges, convert the selection to faces.

OpenMaya is quickest by far, but PyMel is still 4.5x faster then MEL or maya.cmds. What will slow it down however, is if we add a small change - flattening the selection list (i.e.: "ls -sl -fl"):
Timings with selection list flattening:
OpenMaya:0.2 (there is no distinction in the API, same code)

Here it's roughly the same speed as MEL and maya.cmds. What seems to slow it down is creating instances of PyMel classes as we will see in the next example.
Example: custom edge ring select:

PyMel stumbles here, maya.cmds is quicker but OpenMaya turns out nearly 40x faster still. However it's interesting to note that a lot of the PyMel code actually runs 2 or 3 times faster then the maya.cmds code. What slows it down is one part of it, which creates PyMel objects. To be clear, by creating PyMel objects, I mean something like: edge = pymel.core.general.MeshEdge( someMesh, someEdgeIndex ).

The overall conclusion I can draw is that PyMel is quick. A lot of it builds on top of OpenMaya, which is the quickest of all the scripting APIs. Maya.cmds is really just a thin wrapper on top of MEL, and there is no significant performance difference between the two. As long as you can avoid creating a lot of PyMel objects in your code, you should find it outperforming both maya.cmds and MEL.

We know OpenMaya is very quick, but lets compare it to it's non interpreted, compiled flavour: the C++ API. I have a simple plugin deformer implemented in both C++ and Python. It basically takes a point on a curve, calculates a normal to the curve at that point and then bends geometry along that curve. The timings are:

Finding the point along the curve:0.027
Calculating a normal:0.15
Deforming passed points:0.060

Finding the point along the curve:0.017
Calculating a normal:0.0023
Deforming passed points:0.000062

"Finding the point along the curve" is a single function call and most of the work gets done by Maya. There is only a small difference between Python and C++. "Deforming passed points" however, is a bunch of adding and multiplying. No API function gets called. Here C++ outperforms Python by nearly a thousand-fold. The more I work on this plugin the more dramatic the overall difference becomes. For deformers at least, C++ is massively quicker then Python.

These tests are only very limited, I admit, but the medal standings are: gold for C++, silver for OpenMaya, and bronze for PyMel. MEL and maya.cmds are tied for a close fourth.


  1. I was wondering for the non API calls (such as 'deforming passed point' op) it should be possible to optimize python further by using fast math module such as numpy (using numpy array) or Cython (cross compile python code to C), or even PyOpenCL

  2. This comment has been removed by the author.

  3. I was wondering exacltly what Shih proposed (Cython and Numpy for perfomance increases) when I got here.
    Have any of you tried it already? :)