Ah, I figured it out. The 'add' method using a wildcard on a MSelectionList is 
super slow. If you use MGlobal to fill the list for you, it apparently does it 
more efficiently:


start = time.time()

search = "nurbsSphereShape*"
sel = om.MSelectionList()
om.MGlobal.getSelectionListByName(search, sel)
iter = om.MItSelectionList(sel)
depFn = om.MFnDependencyNode()
mObj = om.MObject()

while not iter.isDone():
    iter.getDependNode( mObj )
    depFn.setObject(mObj)
    depFn.findPlug("castsShadows").setBool(True)
    iter.next()
    
end = time.time()-start
print ('api = %s' % end)
# api = 0.212560892105



On Aug 5, 2012, at 5:36 PM, Justin Israel wrote:

> This is an interesting approach:
> 
> start = time.time()
> 
> cmds.select('nurbsSphereShape*')
> size = len(cmds.ls(sl=True))
> cmds.setAttr(".castsShadows", *(1 for _ in xrange(size)))
> 
> end = time.time()-start
> print end
> # 0.243406057358
> 
> ... Though an extra slow down happens if you have to deselect.
> 
> 
> On Aug 5, 2012, at 5:17 PM, Matt Estela wrote:
> 
>> (cc my reply to the group)
>> 
>> 
>> 
>> On Mon, Aug 6, 2012 at 9:16 AM, Matt Estela <[email protected]> wrote:
>> Yeah, again it was a contrived example, in production lighters will 
>> definitely be using whatever bizarro wildcards they can muster.
>> 
>> As you say it appears to be a core limitation of wildcards, will have to 
>> rethink how we let lighters define object selections. In this case maybe we 
>> just can't let lighters use wildcards, instead they'll have to pre-define it 
>> using sets. Or possibly pre-filtering to specific object types, and running 
>> list comprehensions on that.
>> 
>> Hmm, houdini's smart bundles would come in handy here... (dynamic sets based 
>> on wildcards, they run surprisingly fast)
>> 
>> Thanks again for the help Justin, you saved me several days worth of 
>> research. :)
>> 
>> 
>> 
>> 
>> On Mon, Aug 6, 2012 at 5:15 AM, Justin Israel <[email protected]> wrote:
>> Ya, in some cases you can't beat the python commands module if you are only 
>> doing a single command. Most of the work is happening behind the scenes in 
>> C++. The wildcard searches just appear to be beasty no matter what.
>> 
>> But considering you didn't need a wildcard pattern, and instead just want to 
>> say "Apply to all nurbsSurface objects under this root:
>> 
>> #
>> # cmds
>> #
>> start = time.time()
>> sel =cmds.listRelatives('|set', ad=True, type="nurbsSurface")
>> for each in sel:
>>     cmds.setAttr("{0}.castsShadows".format(each), 1)
>> end = time.time()-start
>> print ('cmds = %s' % end)
>> # ** cmds = 0.290652990341 **
>> 
>> #
>> # api
>> #
>> start = time.time()
>> 
>> sel = om.MSelectionList()
>> dagFn = om.MFnDagNode()
>> mObj = om.MObject()
>> dagIt = om.MItDag()
>> 
>> sel.add("|set")
>> sel.getDependNode(0, mObj)
>> dagIt.traverseUnderWorld(True)
>> dagIt.reset(mObj, dagIt.kDepthFirst, om.MFn.kNurbsSurface)
>> 
>> while not dagIt.isDone():
>>     curr = dagIt.currentItem()
>>     dagFn.setObject(curr)
>>     dagFn.findPlug("castsShadows").setBool(False)
>>     dagIt.next()
>> 
>> end = time.time()-start
>> print ('api = %s' % end)
>> # ** api = 0.117326021194 **
>> 
>> 
>> 
>> 
>> On Aug 5, 2012, at 7:01 AM, matt wrote:
>> 
>>> Hmm... did some experimenting. Using your example as a base, I compared 
>>> modifying the castsShadows attr on 8000 spheres. I have them grouped in the 
>>> following way:
>>> 
>>> `-- set
>>>     |-- a
>>>     |   |-- nurbsSphere0001
>>>     |   |-- ...
>>>     |   `-- nurbsSphere4000
>>>     `-- b
>>>         |-- nurbsSphere4001
>>>         |-- ...
>>>         `-- nurbsSphere8000 
>>> 
>>> I get very similar results for both api and maya.cmds. Interestingly, I get 
>>> an incredible slowdown depending on how specific/general I am with the 
>>> search:
>>> 
>>> search = set|*|*|nurbsSphereShape*
>>> api = 27.6180000305
>>> cmds = 27.018999815
>>> 
>>> vs
>>> 
>>> 
>>> search = nurbsSphereShape*
>>> api = 0.956000089645
>>> cmds = 0.403000116348
>>> 
>>> 
>>> This is my first few hours playing with openmaya, already made some silly 
>>> mistakes (defining function-sets inside the loop is waaaay slower than 
>>> outside the loop), but wondering if there's something else I'm missing... 
>>> would appear wildcards should just be avoided at all costs.  Here's my 
>>> contrived example:
>>> 
>>> 
>>> 
>>> import maya.OpenMaya as om
>>> import maya.cmds as cmds
>>> import time
>>> 
>>> #search = "set|*|*|nurbsSphereShape*"
>>> search = "nurbsSphereShape*"
>>> 
>>> print ("search = %s" % search )
>>> 
>>> # API based
>>> start = time.time()
>>> 
>>> sel = om.MSelectionList()
>>> sel.add( search )
>>> iter = om.MItSelectionList(sel)
>>> depFn = om.MFnDependencyNode()
>>> mObj = om.MObject()
>>> 
>>> while not iter.isDone():
>>>     iter.getDependNode( mObj )
>>>     depFn.setObject(mObj)
>>>     depFn.findPlug("castsShadows").setBool(True)
>>>     iter.next()
>>> end = time.time()-start
>>> print ('api = %s' % end)
>>> 
>>> # maya.cmds based
>>> start = time.time()
>>> sel = cmds.ls( search )
>>> for each in sel:
>>>     cmds.setAttr("{0}.castsShadows".format(each), 1)
>>> end = time.time()-start
>>> print ('cmds = %s' % end)
>>> 
>>> 
>>> 
>>> 
>>> On Sunday, August 5, 2012 9:14:06 AM UTC+10, matt wrote:
>>> Wow, definitely seems worth investigating. Thanks for the code snippet and 
>>> timing info!
>>> 
>>> On Sunday, August 5, 2012, Justin Israel wrote:
>>> As a random example...I created a nurbsSphere, and just simulated looping 
>>> over 5000 objects and setting and attrib.
>>> 
>>> import maya.OpenMaya as om
>>> import time
>>> import maya.cmds as cmds
>>> 
>>> sel = om.MSelectionList()
>>> om.MGlobal.getActiveSelectionList(sel)
>>> iter = om.MItSelectionList(sel)
>>> 
>>> obj = om.MObject()
>>> depFn = om.MFnDependencyNode()
>>> 
>>> start = time.time()
>>> for i in xrange(5000):
>>>     iter.getDependNode(obj)
>>>     depFn.setObject(obj)
>>>     depFn.findPlug("tx").setInt(4)
>>> end = time.time()-start
>>> print end
>>> # 0.0979061126709 seconds
>>> 
>>> start = time.time()
>>> for i in xrange(5000):
>>>     name = "nurbsSphere1"
>>>     cmds.setAttr("{0}.tx".format(name), 4)
>>> end = time.time()-start
>>> print end
>>> # 0.261173009872 seconds
>>> 
>>> 
>>> 
>>> 
>>> On Aug 4, 2012, at 12:22 PM, Justin Israel wrote:
>>> 
>>>> Some of the big speed increases are using the iterators and not having to 
>>>> do a bunch of string operations on dag paths. And the math speedups from 
>>>> using the OpenMaya objects with operators.
>>>> 
>>>> Your best bet it to just profile some small tests. You can easily make use 
>>>> of the python `timeit` module to check the difference in speed of 
>>>> operations.
>>>> 
>>>> 
>>>> 
>>>> On Aug 4, 2012, at 10:53 AM, matt wrote:
>>>> 
>>>>> Apologies for the crosspost for anyone on maya_he3d, only remembered this 
>>>>> group existed seconds after I posted over there... Have tried to edit and 
>>>>> re-word for you smart people. :)
>>>>> 
>>>>> Short version:
>>>>> Would using the python OpenMaya module give big speed gains for selecting 
>>>>> thousands of objects and modifying their attributes?
>>>>> 
>>>>> Long version:
>>>>> We have a python based, text based render pass submission tool for 
>>>>> lighters at work. One of its core functions is grabbing whatever geometry 
>>>>> is defined by a lighter, and setting attributes. This sometimes means 
>>>>> adding attributes first (or connecting our custom attribute node), then 
>>>>> setting them.
>>>>> 
>>>>> We're getting into the situation where we have _very_ heavy scenes, with 
>>>>> thousands of objects. Normally our system will process these scenes 
>>>>> within a minute or two per frame, if lighters use wildcards, eg 
>>>>> 'set:tree*', that can jump to maybe 6 mins per frame. Not too bad.
>>>>> 
>>>>> Things get messy with our alembic style heirachical geo format. It can 
>>>>> contain many sub-objects, which our maya plugin doesn't allow us to list 
>>>>> or search for sub-objects names easily. Thus, if a lighter wildcards to 
>>>>> the sub-object level, eg "set:*|leaves*", the only safe way to do that is 
>>>>> to process every object, then every sub-object, unsetting atts those 
>>>>> objects which AREN'T leaves, and setting attrs on those objects which ARE 
>>>>> leaves. When this happens, processing jumps to 3 hours per frame. Yuck!
>>>>> 
>>>>> In the short term we're getting lighters to be more careful with 
>>>>> wildcards, in the mid term getting assets collapsed down so they're not 
>>>>> so name and sub-object heavy, and in the long term getting our geo plugin 
>>>>> more inspectable. So that's good.
>>>>> 
>>>>> I was curious though.... could this be helped in the short(ish) term by 
>>>>> re-writing that part of the code with the OpenMaya module? I recall 
>>>>> reading there's many things which are faster, a few which are slower, and 
>>>>> fewer still which have no OpenMaya equivalent and can only be done in 
>>>>> mel/python. I have a sneaking suspicion one of those slow things was 
>>>>> something fundamental like selection, but I'm hoping I'm wrong.
>>>>> 
>>>>> Was curious if the basic idea of 'yeah, manipulating hundreds of objects 
>>>>> and their attributes is N times faster with OpenMaya' is worth pursuing. 
>>>>> 
>>>>> -matt
>>>>> 
>>>>> -- 
>>>>> view archives: http://groups.google.com/group/python_inside_maya
>>>>> change your subscription settings: 
>>>>> http://groups.google.com/group/python_inside_maya/subscribe
>>>> 
>>> 
>>> 
>>> -- 
>>> view archives: http://groups.google.com/group/python_inside_maya
>>> change your subscription settings: 
>>> http://groups.google.com/group/python_inside_maya/subscribe
>>> 
>>> -- 
>>> view archives: http://groups.google.com/group/python_inside_maya
>>> change your subscription settings: 
>>> http://groups.google.com/group/python_inside_maya/subscribe
>> 
>> 
>> 
>> 
>> -- 
>> view archives: http://groups.google.com/group/python_inside_maya
>> change your subscription settings: 
>> http://groups.google.com/group/python_inside_maya/subscribe
> 

-- 
view archives: http://groups.google.com/group/python_inside_maya
change your subscription settings: 
http://groups.google.com/group/python_inside_maya/subscribe

Reply via email to