[Closed] Memory leakage: what is considered a "large" array?
Hey,
I was just reading that having “large” arrays can cause memory problems in max…but the largeness of the arrays being discussed was not clear.
I have a script that contains several 3d arrays. The largest one has an initial size of 1-10 items, each of those items is an array with 6 items, and each of those items is an array with 500 items. Each item in the 500 item arrays is just a boolean value, string, or integer. So, I guess the total number of items for that array would be around 3,000 – 30,000.
Would this be a problem? I haven’t noticed any problems yet, but I want to be pro-active. Is there anything I can do to avoid memory leaks, other than calling gc? Is there any way I can tell if an array is causing a leak, other than to simply wait for a crash or other weird phenomena in max?
I guess you are referring to my thread The arrays I’ve used aren’t actually huge; I think the problem is more related to the modification of arrays (ie adding and removing items many, many times) rather than array size as such. The actual amount of memory leaked is probably proportional with array size though.
You should also distinguish between a “memory leak” and “heapSize increased automatically”.
MAXScript will increase the HeapSize when it needs more memory and will never decrease it.
My initial HeapSize is set to 64MB because I tend to run scripts with large arrays (the default used to be 7.5MB and might have been increased to 15.0 lately).
I had a script that required 27MB just for an array that I was using to monitor properties in the scene. I have seen my HeapSize go up to over 100MB in some cases. But with 16GB of RAM, this is peanuts.
So you should get the HeapSize before your script runs and then again after running and see if there is a difference. Increased HeapSize is not a memory leak, it is MAXScript adapting to the code you are running. After you restart Max, the initial HeapSize will go down to the value specified in Customize > Preferences > MAXScript.
Krakatoa, Brazil and several other systems pre-increase the HeapSize to at least 32MB or possibly more on startup. You can do the same in your code too – check the HeapSize and if it is below, say, 32MB, increase it yourself to 32MB. This way, you will save time during the script execution because MXS uses smaller steps to increase, and each increase takes time. So it is better to provide enough memory in the beginning instead of waiting for it to happen during the run.
There ARE real memory leaks in many cases, especially when working incorrectly with TriMeshes (like accessing .mesh in a loop without cleaning up afterwards), but that’s not array-related.
Can you expand on this? What do you mean by “cleaning up afterwards”? Is there a list of known issues that cause memory leaks? I don’t remember coming across anything like that in the help docs. I just did a search for “memory leak” and came up nothing. Sounds like it would be a helpful addition, along the lines of the “Making it faster” section.
No, there is no such section. If there are “known memory leaks” in MAXScript functions, they are bugs and Chris P. Johnson is fixing them one by one
But there are ways to leak memory by allocating bitmaps and meshes (which, AFAIK, use Max memory) and not cleaning up after finishing with them. For example, the sample code in the MAXScript Reference for calculating the Volume and Center Of Mass was missing the ‘delete theMesh’ call in its original version, and Larry corrected me because it would leak a TriMesh each time you called it. Sometimes accessing the .mesh property inline could cause that TriMesh to leak until you call gc() if nothing is referencing the value (in other words, it is not assigned to a variable but used directly in a function to operate on it).
That being said, I find MAXScript much less leaky than it was 5-6 releases ago.
I cannot promise a chapter on “how not to leak memory”, but we will see…
i set my initial HeapSize to 128MB. but probably max could never reach this size (usually it crashes before). Small HeapSize causes slowing down MAX loading, instability of script controllers, “leaking” of large arrays… This is what i know for sure.
Ok thanks for the info guys. I’ll implement that heapsize increase that you mentioned, Bobo, if I see it becoming a problem with my script.
Good point about actual memory leaks getting fixed as new versions are released. But there are also some things you can do without realizing it that wouldn’t be considered leaks, but more along the lines of sloppy scripting, or lack of information.
Here’s another example, besides the one with TriMeshes that you mentioned, is building long strings. I was using theString += newString in a large for loop, and Larry pointed out that using format “%” newString to:theString, or print newString to:theString (which is slightly faster) is much better regarding memory usage.
I don’t think he’d mind me posted his comment here:
Building long strings this way can suck down performance, because each “+=” creates a new string value. So you end up with a bunch of string values being created, each of which is slightly longer than the last. And since for string values the memory for the string itself isnt considered as part of the value size in terms of garbage collection, on 32 bit systems you can actually run out of system memory before a mxs garbage collection kicks in and causes all the intermediate values to be collected.
BUT… This is documented already
See
[left]MAXScript FAQ > How To Make It Faster > Use StringStream to build large strings
[/left]
Right, but it doesn’t mention the memory implications of adding strings. You’re just pointing out that’s it’s faster not to (which is good advice in itself). Just saying that it would be nice to have a section of tips on how to not only make your scripts faster, but less crashy as well.
“Use StringStream to build large strings[left]If building strings, use a StringStream value to accumulate the string and then convert to a string.”
[/left]
[left]
[/left]
[left]FOR 100,000 ITERATIONS:
[/left]
[left]
[/left]
[left]test5a() – 58875 msec., 505 MB
[/left]
[left]test5b() – 54672 msec., 39.2 MB
[/left]
[left]test5c() – 41125 msec., 29.2 MB
[/left]
[left]test5d() – 13532 msec., 10.0 MB
I will add a big red warning that not only it is slow, but also memory-intensive (in fact, it IS slow because of the memory allocations)
[/left]