Notifications
Clear all

[Closed] performance and memory usage of my script

i have quite a long script that goes through each object in multiple layers and then stores its material in an array and so on… lots of checks to sort them by name, normal maps, slot name etc and output the formats in a file etc etc etc…

i checked the memory and performance of the script… it takes about 4 seconds for the script to write the file which is about 150 – 200 lines

there are about 120 objects and around 15 different materials involved…

the cpu usage jumps from 2% to 40% and then back to 2% after writing the file
the 3ds max memory usage jumps up by 40MB and then back after the script

i have tried my best to use arrays instead of actual commands but the nature of script has lots of loops etc in it… is this usage amount normal???

13 Replies

There are a number of things you can do to control memory usage. I can’t see if your memory usage is high or low, because you didn’t post the script, but I can give some guide lines.

  1. Declare your varaibles in the correct scope. Use the “local” keyword, and don’t create large arrays as global unless you have a good reason to do so.

  2. When your done with a varaible. Set it to “undefined” to release the reference. If you have working varaibles that store large amounts of data, then they can persist around until their scope is out of range. Unless you set them to undefined.

  3. You can force garbage collection by calling “gc”.

  4. Sometimes it’s just the way you do things. There might be a more effective way or processing the objects. If you post the script we can help.

That’s about it.

Sometimes a script just takes up a lot of time and memory.

thanks for the variable undefined tip… will get that done… sorry cant post the script as its deemed confidential as related to work… although most of the help has come from this forum and the script is too long with multiple include files.

    like i am creating a multisub as array and adding the unique materials of objects to it... that array is used everywher in the script after its completely created.... 
     
     1. so i defined it Global,  this is the only array i.e. Global... is this ok to do this or to return the multisub array from the function that creates it...
  1. here is a function from my script which i definitely think i can optimize but dont know how… probably a switch: case kind of loop but is it worth it? and does max have this function of switch:case…

      --This function goes through each of the submaterial in the Multisub and writes the required info to the file
      --Takes two parameters i.e submaterial of multisub, name of file to write
      function generateMapList mysubfragmaterial out_file = 
      (
		 if (classof mysubfragmaterial) == StandardMaterial then 
      	(
      			 -- For this script, I'm only looking at Diffuse, SpecularL, SpecularC, Opacity & Bump [NormalBump]
    		myfragclass = (classof mysubfragmaterial.diffusemap)
      		if (myfragclass != undefined and myfragclass == BitmapTexture) do
      		(		
      			-- If the targetmap slots have a map but are not checked then enable them
      			mysubfragmaterial.diffuseMapEnable = True
   			format "	Texture \"%\" \"DiffuseTexture\" 
" (filenameFromPath mysubfragmaterial.diffusemap.filename) to:out_file
      		)				
      
   		myfragclass = (classof mysubfragmaterial.specularlevelmap)
   		if (myfragclass != undefined and myfragclass == BitmapTexture) do
      		(		
   			format "	Texture \"%\" \"SpecularLevel\" " (filenameFromPath mysubfragmaterial.specularlevelmap.filename) to:out_file
      		)				
      		
    		myfragclass = (classof mysubfragmaterial.specularmap)
      		if (myfragclass != undefined and myfragclass == BitmapTexture) do
      		(		
   			format "	Texture \"%\" \"SpecularPower\" " (filenameFromPath mysubfragmaterial.specularmap.filename) to:out_file
      		)				
      
      		myfragclass = (classof mysubfragmaterial.opacitymap)
      		if (myfragclass != undefined and myfragclass == BitmapTexture) do
      		(		
   			format "	Texture \"%\" \"Alpha\" " (filenameFromPath mysubfragmaterial.opacitymap.filename) to:out_file
      		)				
      
      		myfragclass = (classof mysubfragmaterial.bumpmap)
      		if (myfragclass != undefined and myfragclass == Normal_Bump) do
      		(
   				 format "	NormalMap \"%\"
" (filenameFromPath mysubfragmaterial.bumpmap.normal_map.filename) to:out_file	
      		)
      		-- Print the name of the sub-material
      			 format "	Material \"%\" 
 
" mysubfragmaterial.name to:out_file
      		 )
      )
      

You should be ok, but it would be better to assign it to undefined when the script is done.

Global variables unlike local varaibles. Will continue to exist in memory even when their reference count is zero.

You can also program memory management logic into your script if you need it. There are global varaibles in MaxScript that reference the amount of free memory.

“heapFree”
“heapSize”

Also, I’m not 100% sure about this, but I think MaxScript’s memory restrictions are different then the application. MaxScript is limited to 512Megs of Ram or something like that. You have to manually override in the 3dsmax.ini file, or something? Sorry, but I can’t remember.

In your sample script source code. I can’t see how it would increase memory of an array.

But, if memory is a problem when calling that function. Try adding the following line to the bottom of the function.

flush out_file

no that is only one of the functions that I think can be optimized as the if loop is recursive but the value keeps changing…

the main global array is not used in this function... it takes a submaterial from that global material and then formats to file..

thanks for all the help btw... 

memory is not a problem at all… just that i am one week old to maxscript so this i my first script. so i was wondering whats “normal” for a script… after reading ur posts i feel quite happy as it only takes 4 secs, 40 MB for 4 secs and does a lot of things for me… so much that it will save 1 day from schedule of each artist’ work…

i was checking the reference and learnt about mapped functions…

did i understand correct that multiple mapped functions can run at the same time… this will be a great optimization because i have a few functions that use the Global material array
and do their job…

I don’t think MaxScript is multi-threaded where two or more functions run at the same time.

Mapped functions allow you to pass an array to a function, but the function is executed for each element in the array.

Very handy when working with selection sets.

If you think that is cool. Read up on the collect keyword.

This will build an array of all the scene materials that are colored red, and it’s 1 line!

example:

redmaterials = for m in sceneMaterials where m.diffuse == red collect m

One of my fav features of MaxScript.

wow great… i am already using the collect command but i think i can use mapped functions now and it should be a huge saving… i will actually cut down my one big loop and pass the whole array…

thanks

i input layers from the user >> suppose the user selects 5 layers… from that point i store the 5 names in an array and want the script to run for each layer…

right now i test only for one and it works… i dont want to add another loop to iterate through each layer but want to use mapped functions… the thing i dont understand is that the script formats lot of data to a file in each round… the only thing i want is that the data for each layer gets outputted to a different file… can this be done while using mapped functions.

1 Reply
(@gravey)
Joined: 11 months ago

Posts: 0

It should be possible. If you defined a global (or private global) variable which will eventually hold the filestream, you can simply define which filestream based on the layer selected just before you call your mapped function. Then in your function you can say format “…” to:<the global variable>
Not sure if there’s a better way but i’m pretty sure this would work

Page 1 / 2