Yes – nothing in that regard has happened – maybe you can stress that on the other board a bit more
could you check the performance for:
(
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)
)
please?
Max 2016 SP3
1 >> time:189
OK
2 >> time:201
OK
Max 2017 SP1
1 >> time:345
OK
2 >> time:341
OK
the same results… it’s bad. it’s more likely caused by new way of executing the mxs. i hoped that the reason was a new way of passing data.
that means we can’t solve on our own this slowdown issue.
Denis:
could you quickly come up with a real usecase where this slowdown gets in the way ? A thing people could run on an existing scene and see the slowdown at once ?
There can’t be many scripts that don’t rely on looping. The simple fact an empty loop takes twice as long should be proof enough of a major issue shouldn’t it?
No – as long as nobody can come up with real use case where this hurts performance in a realworld script i’m sceptical.
And “major issue” would be if this loop slowdown would have happened without the devs changing the relevant code. As i’ve written above, the devs refactored parts and introduced maxscript scope related safety checking code , which in turn increases stability.
The above code by Denis looses 140ms for 1 mio iterations, thats 0.14 microsecs or 140 Nanosecs per iteration. How many maxscript operations do you know that do not take several magnitudes longer ?
I found this in first place working with real scripts, real models, in real world.
So, I wasn’t measuring anything, but I immediately noticed something was slowing things down.
If my internal clock could notice the difference it means it is an issue. I don’t think I can measure microseconds by “eye”.
After I found it, I tried to reduce the problem to the minimum to see what the cause was, and so I came up with the simple loop I posted originally.
As far as I can tell, everything revolves around the iterator itself, no matter what you do inside the loop.
I understand there was some additions to bring stability and debugging features, but it would be nice if we could turn that off and work the same way we have been doing so before.
I would greatly appreciate if “the devs” could shed some light on this and explain why and what is causing the drop in performance. Sometimes I have the felling an internal gc() is kicking in from time to time inside loops, but I have no way to probe it.
Okay some silly code that might show that this is indeed an issue in realworld
and it gets worse with each outer loop iteration
(
function calc a b=
(
result = 1 as float
af = a as float
bf = b as float
for i = a to b do
result = random af bf
result
)
a=1.5
count = 1000
t = timestamp()
for j = 1 to 6 do
(
for k=1 to count*j do
(
a= a* (calc 1 k) / (calc 1 k)
)
format "% >> time:%
" (count*j) (timestamp()-t)
)
)
Max2016 SP3
1000 >> time:543
2000 >> time:3169
3000 >> time:9273
4000 >> time:20008
5000 >> time:36955
6000 >> time:61322
OK
vs.
Max2017 SP1
1000 >> time:960
2000 >> time:4690
3000 >> time:13216
4000 >> time:28614
5000 >> time:52909
6000 >> time:87669
i see the issue and believe it’s a result of ‘improvements’
the ‘iterator’ was #1 reason for me before we didn’t make a test i’ve asked. i’ve asked about the measuring two types of iterating – using from-to and -in-. there’s absolutely different code inside but they behave the same way, causes the same slowdown
i don’t have max 2017 right now, but i guess it’s not about iterating, it’s about going i and out new scope (empty loop body). maybe they changed something recently to decrease memory leaking. if so, it slows down any code.
try these tests:
(
gc()
count = 1000
t = timestamp()
m = heapfree
for k=1 to count do
(
a = matrix3 1
)
format "count:% >> time:% memory:%
" count (timestamp()-t) (m - heapfree)
)
(
gc()
count = 10000
t = timestamp()
m = heapfree
for k=1 to count do
(
a = matrix3 1
)
format "count:% >> time:% memory:%
" count (timestamp()-t) (m - heapfree)
)
(
gc()
count = 20000
t = timestamp()
m = heapfree
for k=1 to count do
(
a = matrix3 1
)
format "count:% >> time:% memory:%
" count (timestamp()-t) (m - heapfree)
)
(
gc()
count = 100000
t = timestamp()
m = heapfree
for k=1 to count do
(
a = matrix3 1
)
format "count:% >> time:% memory:%
" count (timestamp()-t) (m - heapfree)
)
/*
(
gc()
count = 10000000
t = timestamp()
m = heapfree
for k=1 to count do
(
a = matrix3 1
)
format "count:% >> time:% memory:%
" count (timestamp()-t) (m - heapfree)
)
*/
you will see more or less proportional increasing execution time, but absolutely unproportional memory leaking. i was always in all versions. maybe they fixed it 2017?
2016:
count:1000 >> time:1 memory:120L
count:10000 >> time:7 memory:120L
count:20000 >> time:13 memory:33328L
count:100000 >> time:155 memory:2166528L
2017:
count:1000 >> time:1 memory:128L
count:10000 >> time:10 memory:128L
count:20000 >> time:21 memory:128L
count:100000 >> time:102 memory:128L
that’s what i was expecting. they fixed this leaking. but it costs performance
If that is the case, I don’t understand how fixing something that worked well in older versions without any performance drops, would cause the slowdown in Max 2017.
I think the matrix3 leaking was introduced in Max 2012, I haven’t seen it in previous versions. As mentioned in an earlier thread, it can be “fixed” by calling free ‘matrix’ which does not have a big impact in performance.
Besides, there are other values that are not being released, like arrays or bitarrays. I don’t understand what the criteria used to free point3, matrix3, among others and not arrays or bitarrays would be.
(
lower = 3
upper = 5 -- Rising this value will cause bitarrays to eat the RAM
format "POINT3
"
for j = lower to upper do
(
gc(); st=timestamp(); sh=heapfree
for i = 1 to 10^j do a = point3 0 0 0
format " count:% >> time:% memory:%
" (10^j) (timestamp()-st) (sh-heapfree)
)
format "POINT3 - FREE
"
for j = lower to upper do
(
gc(); st=timestamp(); sh=heapfree
for i = 1 to 10^j do
(
a = [0,0,0]
free a
)
format " count:% >> time:% memory:%
" (10^j) (timestamp()-st) (sh-heapfree)
)
format "MATRIX3
"
for j = lower to upper do
(
gc(); st=timestamp(); sh=heapfree
for i = 1 to 10^j do a = matrix3 1
format " count:% >> time:% memory:%
" (10^j) (timestamp()-st) (sh-heapfree)
)
format "MATRIX3 - FREE
"
for j = lower to upper do
(
gc(); st=timestamp(); sh=heapfree
for i = 1 to 10^j do
(
a = matrix3 1
free a
)
format " count:% >> time:% memory:%
" (10^j) (timestamp()-st) (sh-heapfree)
)
format "ARRAY
"
for j = lower to upper do
(
gc(); st=timestamp(); sh=heapfree
for i = 1 to 10^j do a = #(i)
format " count:% >> time:% memory:%
" (10^j) (timestamp()-st) (sh-heapfree)
)
/* CARREFUL! If you rise the upper iteration limit over 5, the following loop will start eating the RAM */
format "BITARRAY
"
for j = lower to upper do
(
gc(); st=timestamp(); sh=heapfree
for i = 1 to 10^j do a = #{i}
format " count:% >> time:% memory:%
" (10^j) (timestamp()-st) (sh-heapfree)
)
)
MAX 2016
POINT3
count:1000 >> time:1 memory:64L
count:10000 >> time:5 memory:64L
count:100000 >> time:55 memory:6364888L
POINT3 – FREE
count:1000 >> time:1 memory:64L
count:10000 >> time:6 memory:64L
count:100000 >> time:60 memory:64L
MATRIX3
count:1000 >> time:0 memory:64L
count:10000 >> time:5 memory:64L
count:100000 >> time:59 memory:12656704L
MATRIX3 – FREE
count:1000 >> time:1 memory:64L
count:10000 >> time:7 memory:64L
count:100000 >> time:65 memory:64L
ARRAY
count:1000 >> time:1 memory:104488L
count:10000 >> time:5 memory:1459208L
count:100000 >> time:64 memory:13030536L
BITARRAY
count:1000 >> time:1 memory:64064L
count:10000 >> time:5 memory:656480L
count:100000 >> time:203 memory:6485008L
MAX 2017
POINT3
count:1000 >> time:0 memory:68L
count:10000 >> time:7 memory:68L
count:100000 >> time:70 memory:68L
POINT3 – FREE
count:1000 >> time:1 memory:68L
count:10000 >> time:10 memory:68L
count:100000 >> time:97 memory:68L
MATRIX3
count:1000 >> time:1 memory:68L
count:10000 >> time:7 memory:68L
count:100000 >> time:70 memory:68L
MATRIX3 – FREE
count:1000 >> time:1 memory:68L
count:10000 >> time:10 memory:68L
count:100000 >> time:99 memory:68L
ARRAY
count:1000 >> time:1 memory:137164L
count:10000 >> time:9 memory:1551384L
count:100000 >> time:100 memory:13828696L
BITARRAY
count:1000 >> time:1 memory:68068L
count:10000 >> time:8 memory:696964L
count:100000 >> time:229 memory:6868988L