Plugin slower than normal cmds execution??

137 views
Skip to first unread message

Benjam901

unread,
Apr 3, 2016, 6:54:16 AM4/3/16
to Python Programming for Autodesk Maya
Hello all,

I have been digging into the Maya API dungeons recently to get myself up to speed and familiar with the Maya API.

I have found myself recently digging through hierarchies to get all nodes of a prefix or of type. I find myself constantly using:

for i in pm.listRelatives(object):
    if i.startswith('prefix'):
        do stuff...

So I decided to write myself a small plugin for a learning task that does this for you.


The only problem is the speed of the plugin, I put the plugin and the original for i in relatives in 2 functions and used timeit in the maya script editor. 
The normal list relatives function was faster which seriously confused me because I am sure that the API is supposed to be much faster at processing information, I have a feeling I have some serious inefficiencies in my plugin so any tips would go a long way to help me out!

Here is the Maya script editor testing:

import maya.cmds as cmds

getObjPluginPath = "path to get_objects_under_node.py"

cmds.loadPlugin(getObjPluginPath)

sel = cmds.ls(sl=True)
def pluginWay():
    for s in sel:
        cmds.getObjsUnderNode(s, fn='c_')
        
def normalWay():
    for s in sel:
        myList = []
        for i in cmds.listRelatives(s, ad=True, fullPath=True):
            if i.startswith('c_'):
                myList.append(i)
        #print myList
        
import timeit
timeit.Timer(pluginWay).timeit(number=500)
timeit.Timer(normalWay).timeit(number=500)

Marcus Ottosson

unread,
Apr 3, 2016, 9:09:12 AM4/3/16
to python_in...@googlegroups.com

I know the goal isn’t to solve this particular problem, but to learn more about the API. But in case you didn’t already know, ls with wildcard can do some of this for you.

# Find nodes with prefix
cmds.ls("prefix_*")

# Find nodes with suffix
cmds.ls("*_suffix")

# Find nodes of type
cmds.ls(type="locator")

# Find nodes with suffix, that are children at 2nd level of a hierarchy
cmds.ls("|myParent|*|*_suffix", dag=True)

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/66fc6191-2361-4c99-b954-ea8550863ba2%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
Marcus Ottosson
konstr...@gmail.com

Ben Hearn

unread,
Apr 3, 2016, 9:14:26 AM4/3/16
to python_in...@googlegroups.com
Aha! I knew I was missing something with ls!

Thanks for the heads up I have been looking for this for ages. Still, was good to actually jump into the API :)

--
You received this message because you are subscribed to a topic in the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/python_inside_maya/rnrBzWARs1c/unsubscribe.
To unsubscribe from this group and all its topics, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAFRtmODBFdyk4wKHdNPdNzF_mV%2BstW4AwiRNsjfn_fst4ykB3Q%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.



--

Tel - +46 76245 92 90 (Sweden)

Ian Jones

unread,
Apr 3, 2016, 11:53:16 AM4/3/16
to python_in...@googlegroups.com

Hey Ben,

That's because your plugin is built in Python. The native commands are implemented against the C API which is much faster. Your native example spends less time in python and more in C which is probably why your seeing those results.

The good news is it's a relatively straight forward port from Python API to C if your interested. I commonly prototype plugins in Python then port myself if I don't need performance right away.

Also if your interested in performance I'd suggest using the profile/cProfile module over time it as it'll help you better understand your code and where the time is spent.

Ian


Ben Hearn

unread,
Apr 3, 2016, 12:19:12 PM4/3/16
to python_in...@googlegroups.com
Ah I see, thanks for the tip. So is it advised to port from python to C++ when you actually want to roll out the plugin?


For more options, visit https://groups.google.com/d/optout.

Ian Jones

unread,
Apr 3, 2016, 12:37:52 PM4/3/16
to python_in...@googlegroups.com
I think that's entirely how perf dependant you are.

We commonly roll new features out unoptimized just to see if the art team uses them. Many of the tools they don't even bother to ask to make faster vs getting another tool sooner. Others we spend months optimizing for the best possible iteration. It's very much a case by case basis.

Ian


Ben Hearn

unread,
Apr 3, 2016, 12:54:35 PM4/3/16
to python_in...@googlegroups.com
From a general plugin development perspective how much work would a general plugin actually do. For example writing an entire tool, would you mix and match with specific bits being a plugin or the entire functionality be wrapped into one plugin? Or as you said would it be more a case by case basis?

- Ben


For more options, visit https://groups.google.com/d/optout.

Justin Israel

unread,
Apr 3, 2016, 3:28:22 PM4/3/16
to python_in...@googlegroups.com

Hey Ben,

As mentioned, the slowness is because you are comparing a python plugin to a C solution. The part of your code that takes the biggest hit is that while loop. Python is doing so many reflection operations, functions calls, and allocations, which is why loops in python will be the killer.

You don't always have to implement your plugins in C. Only when they have performance bottlenecks. There are plenty of applications where you aren't iterating the scene and doing tons of functions calls and object creation. So best to just profile your code and fine the hotspots. Your options for slow python plugins are either to write the entire plugin in C++ or to just write some speed up utilities for slow operations and call them as exposed commands.

I think I even tried writing a simple ls command using Cython a long time ago to see if it would work, and it did. That means you could write some stuff in Cython


Ben Hearn

unread,
Apr 4, 2016, 8:45:31 AM4/4/16
to python_in...@googlegroups.com
Hey Marcus,

I was wondering about the ls wildcard. I have been trying it out properly today and it only seems to get the nodes on the top level of the root, i.e. it will not dig down and give me my inner children. Am I missing a flag combination, I have tried pretty much all of them and no luck O.o

Cheers,

Ben


For more options, visit https://groups.google.com/d/optout.

Marcus Ottosson

unread,
Apr 4, 2016, 1:11:15 PM4/4/16
to python_in...@googlegroups.com

It shouldn’t care much about children, but rather look at the graph as a whole.

Here’s an example that works for me, returning an inner child.

cmds.file(new=True, force=True)
cmds.polyCube(name="myCube1")
cmds.polyCube(name="myCube2")
cmds.group(name="myGroup")
assert "myCube2" in cmds.ls("*2")


For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

Ben Hearn

unread,
Apr 6, 2016, 5:39:29 AM4/6/16
to python_in...@googlegroups.com
Thanks for the tips man! 
I have one other question that has been bugging me for some time. 

A colleague of mine mentioned he never uses PyMel because cmds sits closer to the mel side of things, so I was wondering about speed of execution between the two. 

From a personal preference I really like PyMel, there are some extra bits in there that make life super easy and syntactically pm and cmds are very similar. I did some digging about this and the results were always the same "its personal preference"

Is there truly any massive speed benefit in using cmds vs pm? 

- Ben


For more options, visit https://groups.google.com/d/optout.

Marcus Ottosson

unread,
Apr 6, 2016, 5:47:00 AM4/6/16
to python_in...@googlegroups.com
There are so many discussions about that already on this list, so I won't comment on that.


For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

Ben Hearn

unread,
Apr 6, 2016, 5:47:37 AM4/6/16
to python_in...@googlegroups.com

Joe Weidenbach

unread,
Apr 6, 2016, 5:48:00 AM4/6/16
to python_in...@googlegroups.com
The major speed benefits seem (from my experience) to come from using the api directly. Pymel is definitely slower overall, and I've run into issues in the past with older versions having bugs (although to be fair, what software doesn't?)

With that said, the speed of development and ease of maintenance could arguably make it much more worthwhile to use pymel for everyday tasks. It's certainly much more usable for tools that manipulate object names, as one example. From what I've seen, I'd argue that when the slowdown you get from pymel over maya.cmds becomes an issue, it's time to start looking at the api or even a full c++ treatment.

With that said, I also know that there are some studios that don't use pymel as a rule, so it's always good to be flexible too -- Make sure you at least know maya.cmds pretty well before you switch over :)

Just my two cents

haggi...@gmail.com

unread,
Apr 6, 2016, 5:48:02 AM4/6/16
to Python Programming for Autodesk Maya
Indeed, pymel is a wrapper and is often slower than mel or maya.cmds.
But it depends. If you need speed, e.g. if you want to manipulate a lot of points, then there is a huge speed difference.

We use pymel for all non speed critical things and c++ or maya python api for everything else what is a very nice combination.
Reply all
Reply to author
Forward
0 new messages