Notifications
Clear all

[Closed] MXS 2017 'For Loop' performance

it looks like i will wait for even version. as usually…

3 Replies
(@polytools3d)
Joined: 10 months ago

Posts: 0

Do you really think this will be fixed/improved in next mayor version?

The developers are already aware of this. However, all I read is:

  • This is “by design” (developers love to say this)
  • Give me a real example as a proof.

If the best response you get is the worse excuse you’ve heard, nothing will change.

(@denist)
Joined: 10 months ago

Posts: 0

not really. because I see 2,500 views of this topic, and only ten people who wants to talk…

most of the users just don’t care that a ‘find all hidden edges’ one day will work ~40 times slower.

I’m OK. I always didn’t believe too much max developers. I’ve wrote my ‘iterator’ class which works ~70% faster than max built-in… it looks like:

for i in iterator #(1,2,3000)  do ()
for i in iterator #{1..3, 10000}   do ()
for i in iterator 10  do ()
for i in iterator 2 12   do ()
for i in iterator 1 100 by:3   do ()
-- etc...
(@deadclown)
Joined: 10 months ago

Posts: 0

I’m very interested in it, but I don’t usually post a “+1” reply on a topic. I don’t have anything useful to add to the discussion but I really want this to be fixed. I just hope that the right people realize that it’s an issue (yeah, I know… )

i believe in max developers conscience

the built-in max has iterators (mapping)… but at the first its converts a mappable value to ‘iteratable’.
i do it on-the-fly. so my iteration is faster at least on the time of conversion…

I can only give my full support to this initiative. It is an unacceptable bug for users and programmers.

Sorry for reviving this thread, but since SP3 is out and there seems to no improvment so far I feel a bit worried about these problems.

If you guys wan’t an example of something really slow try the code below,
this code is part of a small fix for attaching meshes with edit normals and inverted transforms without any issues (until now)

(
function NormalizeObjectNormals obj =
(
local m3_transform = obj.transform
m3_transform.pos = [0,0,0] – remove position as a factor from the normal calculation

	local p3_normal
	local vertexCount = obj.numVerts
	local i = 0
	local ar = #()

	while i < vertexCount do 
	(
		i +=1
		p3_normal = getNormal obj i
		setNormal obj i (p3_normal * m3_transform)
	)
	
	update obj geometry:false topology:false normals:true
)

b = box heightsegs:30 lengthsegs:30 widthsegs:30
convertToMesh b
local tm = timestamp()
NormalizeObjectNormals b
local totalTime = (timestamp() - tm) / 1000.0

format "Time: %s

” totalTime
)

30 segments
Max 2014 SP5: time:22
Max 2017 SP3: time:3757

40 segments
Max 2014 SP5: time:38
Max 2017 SP3: time:14692

50 segments
Max 2014 SP5: time:57
Max 2017 SP3: time:37061

100 segments
Max 2014 SP5: time:348
Max 2017 SP3: time:638625

Submit a Bug Report, this shouldn’t happen…

The slow operation here is setnormal() ( can easily be verfied by simply commenting it out )
It’s not the loop performance per se
Noteworthy from the the maxscript help for setnormal()

Since 3ds Max 2015, setting a vertex normal sets the normal as Explicit, so it will retain its value when the mesh gets updated. In versions prior to 3ds Max 2015, setting the vertex normal using MAXScript had only a very short lasting effect because the data would be easily overwritten by the Smoothing Group-based implicit normal recalculation on viewport redraw or scene rendering.

So it sounds logical that the performance takes a hit, compared to the Max 2014 version. But i tested in Max 2015, and the performance hit is not as huge as in Max 2017. i get those numbers

Max 2014: 0.015s
Max 2015: 0.481s
Max 2016: 0.486s
Max 2017: 2.204s

But again – the performance hit is not from the loop, but from the SetNormal operation itself. So this should be reported IMHO…

I modified the code to use the edit_normals modifier instead ( did not really check wether it really works correctly on the normals though, so better verify that) and using that one improves the performance a good deal with Max 2017 ( this method runs even faster in Max 2017 than the Max 2014 counterpart but overall slower as the original code on Max 2014)

Time for 30 segs on Max 2017: 0.395s

(
    function NormalizeObjectNormals obj =
    (
        local m3_transform = obj.transform
        m3_transform.pos = [0,0,0] -- remove position as a factor from the normal calculation

        local p3_normal
        local i = 0
        local ar = #()

-- new code 
        
        addModifier obj (editnormals())
        setCommandPanelTaskMode #modify
        select obj
            
        getFnCached = obj.Edit_Normals.GetNormal 
        setFnCached = obj.Edit_Normals.SetNormal 

        for i=1 to obj.Edit_Normals.GetNumNormals() do
            setFnCached  i ((getFnCached i) * m3_transform)
        
        format "% normals processed...
" (obj.Edit_Normals.GetNumNormals())
        collapseStack obj   
            
/* original code
        local vertexCount = obj.numVerts
            
        while i < vertexCount do
        (
            i +=1
            p3_normal = getNormal obj i
            setNormal obj i (p3_normal * m3_transform)
        )

        update obj geometry:false topology:false normals:true           
*/          
            
    )

    b = box heightsegs:30 lengthsegs:30 widthsegs:30
    --convertToMesh b
    local tm = timestamp()
    NormalizeObjectNormals b

    local totalTime = (timestamp() - tm) / 1000.0

    format "Time: %s
" totalTime
)

Swordslayer
I’ve submited one now, thanks for the link

spacefrog
ah yeah sorry about hijacking the tread, as you say this is a differn’t issue.
Interesting to see that its actually faster to use the edit normals modifier instead, I did actually have that one in an earlier development version but removed it due to the slow speed;)

look like in max 2018 theres slight increase performance


--- from Denis T
(
	count = 1000000
	t = timestamp()
	for k = 1 to count do ()
	format "1 >> time:%
" (timestamp()-t)
)
(
	count = 1000000
	bits = #{1..count}
	t = timestamp()
	for k in bits do ()
	format "2 >> time:%
" (timestamp()-t)
)
-- // Result \\

-- 1 >> time:88
-- 2 >> time:95


--- From Jorge (PolyTools3D)

(
st = timestamp()
for j = 1 to 1000000 do ()
format "time:%
" (timestamp()-st)
)

--// Result \\
-- time:90


Page 8 / 9