Home Coding, Scripting, Shaders

Maxscript: why storing frequently used function in variable doesn't make access to function faster?

There is a nice advice in MAXScript FAQ: Cache frequently used functions and objects but it doesn't work for me (at all).

Why?

Script example:

(16000 iteration in for loop)

        startTime = timeStamp()
        firstSelectedBaseobject = selection[1].baseobject
        edgesBetweenMatIDs = #()
        edgesNumber = polyOp.getNumEdges firstSelectedBaseobject
        getFacesUsingEdge = polyOp.getFacesUsingEdge --I'm cashing function in variable but performance isn't changing
        for edge = 1 to edgesNumber do
        (
            neighbourFaces = (getFacesUsingEdge firstSelectedBaseobject #(edge)) as array
            if neighbourFaces.count == 2 do
            (
                matID1 = polyOp.getFaceMatID firstSelectedBaseobject neighbourFaces[1]
                matID2 = polyOp.getFaceMatID firstSelectedBaseobject neighbourFaces[2]
                if matID1 != matID2 then
                (
                    append edgesBetweenMatIDs edge
                )
            )
        )
        polyOp.setEdgeSelection firstSelectedBaseobject edgesBetweenMatIDs
        format "Time %s\n\n" ((timeStamp() - startTime) / 1000.0)

How to optimize polyOp.getFacesUsingEdge?


Replies

  • poopipe
    Options
    Offline / Send Message
    poopipe grand marshal polycounter
    It's not something I've ever really looked into but...

    I'm not sure you're actually caching the result of that function. I think it still has to work out the conversion based on the current selection which is what will take the time. You would presumably need to pass in the object and edge selection when you declare getFacesUsingEdge in order to see any benefit and that won't work in the context you're using it. 

    I suspect its the per edge iteration that's taking the time rather than than the selection conversion though. if speed is important I'd suggest rethinking how you gather the information you need. 


  • 3dyuriki
    Options
    Offline / Send Message
    Thanks for answer!
    My goal is to get faces using edge (for plenty of edges in a loop). And this operation (polyOp.getFacesUsingEdge) is very heavy (like 2 seconds for 16000 operations).
    What else methods can I use to improve performance?

  • monster
    Options
    Offline / Send Message
    monster polycounter
    Normally caching the function works really well. But you're correct it has no effect on this particular function.

    I took a pass on the script it went from 1.08 seconds to 0.04 seconds. The basic ideas to make things faster (with MaxScript) are avoid using memory in loops, and avoid converting data types especially in loops.

    --//CACHE polyOp.getFaceMatID AS WELL
    --//DON'T USE polyOp.getFacesUsingEdge
    --//DON'T CONVERT neighbourfaces TO ARRAY... ENDED UP NOT NEEDING IT AT ALL WITH THE EDITABLE POLY METHOD
    --//USE FEWER VARIABLES, REMOVED mat1 and mat2
    --//USE A BITARRAY FOR edgesBetweenMatIDs <br>
    
    (
    	
    	startTime = timeStamp()
    	firstSelectedBaseobject = selection[1].baseobject
    	edgesNumber = polyOp.getNumEdges firstSelectedBaseobject
    	edgesBetweenMatIDs = #{}
    	getFacesUsingEdge = firstSelectedBaseobject.editablePoly.GetEdgeFace
    	polyOpGetFaceMatID = polyOp.getFaceMatID
    	
    	for edge = 1 to edgesNumber do
    	(
    		neighbourFaces1 = (getFacesUsingEdge edge 1)
    		neighbourFaces2 = (getFacesUsingEdge edge 2)
    			
    		if neighbourFaces1 != 0 and neighbourFaces2 != 0 do
    		(
    			edgesBetweenMatIDs[edge] = \
    				not (polyOpGetFaceMatID firstSelectedBaseobject neighbourFaces1 \
    				== polyOpGetFaceMatID firstSelectedBaseobject neighbourFaces2)
    		)
    	)
    
    	polyOp.setEdgeSelection firstSelectedBaseobject edgesBetweenMatIDs
    	format "Time %s\n\n" ((timeStamp() - startTime) / 1000.0)
    )

  • 3dyuriki
    Options
    Offline / Send Message
    OMG! Thank you for GetEdgeFace! How could I miss it...

  • PolyHertz
    Options
    Offline / Send Message
    PolyHertz polycount lvl 666
    Just fyi for Editable Poly you should instead use PolyOp.getEdgeFaces, (faces not face) as it's MUCH faster (up to 330x as fast from my tests).
Sign In or Register to comment.