Disable Undo system when possible

MAXScript FAQ > How To Make It Faster > Disable Undo system when possible

The undo system can consume large amounts of memory and slow down processing.

TEST CASE:

em = mesh()
meshop_setvert = meshop.setvert
fn test7 holdAll =
(
 local nVerts = getnumverts em
 for i = 1 to nVerts do
  with undo (holdAll or (i == 1 or i == nVerts))
   meshop_setvert em i ([1,1,1]*i)
)

FOR 100,000 ITERATIONS:

test7 true -- 85313 msec., 229 MB
test7 false-- 7609 msec., 11 MB

Every operation that creates an undo record will cost time and memory as it will create internal copies of the changing objects to allow an undo later. When making multiple changes in a loop like for example attaching multiple objects together, the Undo system would attempt to create a single undo copy of each resulting object and might even run out of memory. Disabling Undo explicitly using the Undo off () context can help to speed up scripts significantly in such cases.

undo

The following extreme example shows the difference. In both cases, 1000 boxes will be created using MAXScript and then attached to a single mesh using the attach function. In the first case, each attach call will generate by default an undo record. In the second case, the undo will be explicitly disabled.

EXAMPLE 1 - UNOPTIMIZED SCRIPT:

delete $Box*--delete any existing boxes
box_array = #()--initialize an array
for i = 1 to 1000 do--repeat 1000 times
  box_array[i] = box pos:[i*30,0,0]--create 1000 boxes
st = timestamp()--get the start time in milliseconds
master_box = convertToMesh box_array[1]--collapse the first box to mesh
for i = 2 to 1000 do--go through all other boxes
  attach master_box box_array[i]--attach each box to the mesh
et = timestamp()--stop the time
print (et-st)--print the resulting time
gc()--call Garbage Collection &endash; you will needed it!

On a 800MHz PC, the execution of the attaching part of the script took more than a minute mainly because the system run out of memory and the OS had to swap to disk. Memory usage for 3ds Max went up with about 300 MB!

EXAMPLE 2 - OPTIMIZED SCRIPT:

delete $Box*
box_array = #()
for i = 1 to 1000 do
box_array[i] = box pos:[i*30,0,0]
st = timestamp()
undo off--the only difference - the undo
(--has been turned off
  master_box = convertToMesh box_array[1]
for i = 2 to 1000 do
  attach master_box box_array[i]
)--end undo off
et = timestamp()
print (et-st)
--call Garbage Collection - you will needed it!

On the same 800MHz machine, the execution of the attaching part of the script took only 3685 milliseconds, almost 20 times faster! There were no memory consumption changes visible in the Windows Task Manager.

Previous Tip

Disable Viewport Redraws when making changes to scene objects

Next Tip

Modify Panel can be slow -change to Create Panel when possible