[Closed] Fastest way to add keys on controller.
Dang… my bad…
I was using “instanceReplace” instead of “replaceInstance”
Now everything is working.
This is what I’m doing.
- I made a new controller
- add keys with “AddNewKey” and set value and tangent with SetProperty.
- update old controller with “replaceInstance”.
This way I can keep instance and wiring while not triggering notification when I add keys.
In my tests, using ‘at time’, is exponentially faster than accessing the controller, even if you don’t use disableRefMsgs().
These are some results:
Iterator:
for t=0 to 20000 do for k=1 to 3 do ()
Max 2011 (controller)
time:920 ram:1160L – with disableRefMsgs()
time:1169 ram:1160L
Max 2011 (at time)
time:85 ram:704L – with disableRefMsgs()
time:162 ram:704L
Max 2104 (controller)
time:1587 ram:1160L – with disableRefMsgs()
time:1983 ram:1160L
Max 2104 (at time)
time:76 ram:704L – with disableRefMsgs()
time:184 ram:704L
Here are another two tests with addnewkey() only, no values are set.
(
iterations = 20000
controller = Euler_XYZ()
st=timestamp(); sh=heapfree
for t = 0 to iterations do addnewkey controller[1].controller t
format "time:% ram:%
" (timestamp()-st) (sh-heapfree)
controller = Euler_XYZ()
st=timestamp(); sh=heapfree
addnewkey controller[1].controller iterations -- SLOW DOWN !? BUG !?
for t = 0 to iterations do addnewkey controller[1].controller t
format "time:% ram:%
" (timestamp()-st) (sh-heapfree)
)
MAX 2011
time:276 ram:416L
time:8162 ram:416L ??
MAX 2014
time:499 ram:416L
time:10729 ram:513216L ??
Interesting…
I also thought at time would be slower.
Thanks for new tip!
i’m not sure but i remember that add keys to a controller in old versions of max didn’t do automatic key sorting. in my old scripts i usually do sort after adding keys.
but as i see now (in max 2014) all key-time operations do sorting. sorting forces the controller evaluation on full interval. when you set a ‘far’ key you makes this interval long.
i’ve tested my sdk mxs extension and found that all add-new-key related methods are slower now.
it sucks. i don’t have an idea what we can do. but the issue definitely needs a solution.
for at time the situation is the same – very SLOW:
(
iterations = 20000
controller = Euler_XYZ()
st=timestamp();
sh=heapfree
addnewkey controller[1].controller iterations -- SLOW DOWN !? BUG !?
animate on for t = 0 to iterations do at time t controller[1].controller.value = controller[1].controller.value
format "time:% ram:% keys:%
" (timestamp()-st) (sh-heapfree) controller.keys.count
)
memory is OK because setting a value doesn’t return a MAXKey (doesn’t create a new mxs Value)
Yes, it is the same for ‘at time’. And it’s not only since 2014, I can confirm this behavior since 2011 as showed in the previous tests.
It might be a feature, but looks like a bug to me.
i’ve rewrote the snippet above on sdk c++ and it does do the same job for 25 msec
i’ve double-checked. it slows down because of sorting. if i add (using sdk) all keys without sorting it’s fast. with the sorting after adding every new key it takes 7-8 secs (which is almost close to mxs (12 secs))
A quick MXS workaround in this situations could be to fill the keys array in reverse order.
It is not as fast as working with a controller without keys, but definitely much faster than setting the keys in ascending order.
I am not sure how this can affect some animations, so it would be good if someone can test it and report any issues they find.
(
gc()
delete objects
iterations = 20000
controller = Euler_XYZ()
st=timestamp(); sh=heapfree
animate on for t = 0 to iterations do at time t controller[1].controller.value = t
format "time:% ram:% keys:%
" (timestamp()-st) (sh-heapfree) controller.keys.count
b = box pos:[0,0,0] wirecolor:red
replaceinstances b.rotation.controller controller
controller = Euler_XYZ()
st=timestamp(); sh=heapfree
addnewkey controller[1].controller iterations
animate on for t = 0 to iterations do at time t controller[1].controller.value = t
format "time:% ram:% keys:%
" (timestamp()-st) (sh-heapfree) controller.keys.count
b = box pos:[30,0,0] wirecolor:green
replaceinstances b.rotation.controller controller
controller = Euler_XYZ()
st=timestamp(); sh=heapfree
addnewkey controller[1].controller iterations
animate on for t = iterations to 0 by -1 do at time t controller[1].controller.value = t
format "time:% ram:% keys:%
" (timestamp()-st) (sh-heapfree) controller.keys.count
b = box pos:[60,0,0] wirecolor:blue
replaceinstances b.rotation.controller controller
)
MAX 2011
time:30 ram:416L keys:20001 – Empty
time:7815 ram:416L keys:20001 – Ascending
time:318 ram:424L keys:20001 – Reverse
MAX 2014
time:29 ram:416L keys:20001 – Empty
time:10138 ram:153824L keys:20001 – Ascending
time:296 ram:1203808L keys:20001 – Reverse
Nevermind, the workaround won’t work in most real situations:
(
gc()
delete objects
iterations = 20000
controller = Euler_XYZ()
st=timestamp(); sh=heapfree
animate on for t = 0 to iterations do at time t controller[1].controller.value = t
format "time:% ram:% keys:%
" (timestamp()-st) (sh-heapfree) controller.keys.count
b = box pos:[0,0,0] wirecolor:red
replaceinstances b.rotation.controller controller
controller = Euler_XYZ()
st=timestamp(); sh=heapfree
addnewkey controller[1].controller 0
addnewkey controller[1].controller (iterations/2)
addnewkey controller[1].controller iterations
animate on for t = 0 to iterations do at time t controller[1].controller.value = t
format "time:% ram:% keys:%
" (timestamp()-st) (sh-heapfree) controller.keys.count
b = box pos:[30,0,0] wirecolor:green
replaceinstances b.rotation.controller controller
controller = Euler_XYZ()
st=timestamp(); sh=heapfree
addnewkey controller[1].controller 0
addnewkey controller[1].controller (iterations/2)
addnewkey controller[1].controller iterations
animate on for t = iterations to 0 by -1 do at time t controller[1].controller.value = t
format "time:% ram:% keys:%
" (timestamp()-st) (sh-heapfree) controller.keys.count
b = box pos:[60,0,0] wirecolor:blue
replaceinstances b.rotation.controller controller
)
MAX 2011
time:27 ram:416L keys:20001
time:7791 ram:416L keys:20001
time:8033 ram:432L keys:20001
I don’t know why, but when I used replaceInstances on complex rig.
It broke rig.
Also even with refMsg off and PolyTools3D trick, it was slower then builtin animation save/load.