Maya API: File translators - OpenMaya vs C++ speeds?


#1

I am curious about what kind of performance gains there is to get from re-writing an existing Maya plugin - tool or file translator(exporter) - into pure C++ (Maya API). As you might know you can write plugins just fine with the OpenMaya module but Python is significantly slower than C++.

Does anyone have any numbers here? Other thoughts? What are the eventual pitfalls?

I’m thinking about the maintenance part for instance: Having the tool or exporter in Py means that other TA’s can maintain and extend it easily (but devs will be less prone to do so)… and if the tool is written in C++ it’s the other way around (TA’s less prone to maintain it because C++ skills are less common within our discipline).


#2

I tend to operate on the idea that python is anywhere from 10-100 times slower than properly written C.
OpenMaya is faster than regular old pure python code, as it is calling the same C-functions, but with overhead due to the binding / translation layer.

I’ve never actually written any C++ for Maya, so my opinion probably isn’t the most helpful.

But for me the pro’s on the python side are forward compatibility without having to recompile, and a language that I hate less.

The only pro I’d usually lend towards C++ in this kind of comparison is raw execution speed.

Also, if you’ve got developers that aren’t willing to throw in maintenance / support on a part of the toolchain just because it was written in Python, well I’d sincerely ask why they think that is a reason to avoid part of their job?


#3

Some things you just have to write in C++ to make them fast enough usable. However, my co-worker and I have found a really neat trick to make some things viable in Python that weren’t before.

Using OpenMaya.MScriptUtil, you can get SWIG array objects for most numeric types, which you can memoryMap directly into numpy by going through ctypes. So that means, when dealing with large arrays of numbers, you can sometimes bypass python altogether. Accessing the skin weights and displaying them in a QTableView was taking 3 or 4 seconds with MDoubleArrays. With this technique, we got it down to .2 sec.

You can set the data in the same way. Just get the reference numpy object, and fill it with whatever data you want.
Be very careful with this, though. Getting data by pointer in python doesn’t increment the reference count, so you can easily corrupt memory outside of your array if the MScriptUtil object gets garbage collected.

Example:

from maya import OpenMaya as om
from ctypes import c_double
import numpy as np
import time

start = time.time()
# create a dummy array for testing purposes
pa = [float(i) for i in range(1000000)]
util = om.MScriptUtil()
util.createFromList(pa, len(pa))
end = time.time()
print "Allocation and copying took:", end - start


start = time.time()
# cast the scrptUtil object to a swig double pointer
ptr = util.asDoublePtr()
# Cast the swig double pointer to a ctypes array
cta = (c_double * len(pa)).from_address(int(ptr))
# Memory map the ctypes array into numpy
out = np.ctypeslib.as_array(cta)
# ptr, cta, and out are all pointing to the same memory address now
# so changing out will change ptr

# for safety, make a copy of out so I don't corrupt memory
out = np.copy(out)
end = time.time()
print "Getting the numpy interface took:", end - start