Notifications
Clear all

[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.

  1. I made a new controller
  2. add keys with “AddNewKey” and set value and tangent with SetProperty.
  3. 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)

1 Reply
(@polytools3d)
Joined: 1 year ago

Posts: 0

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

1 Reply
(@polytools3d)
Joined: 1 year ago

Posts: 0

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.

Page 2 / 2