Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I prevent OutOfMemory Exceptions during Array.Resize?

My current project includes a vegetation simulation, capable of rendering a large number of instanced tree models that grow and reproduce over time.

I'm currently getting consistent OutOfMemory exceptions on this line of code

if (treeInstances.Length <= currentIndex)
    Array.Resize(ref treeInstances, currentIndex + 500);

This code runs when the simulation exceeds the usual bounds of the treeInstances array, and causes it to allocate a new array with an additional 500 slots for trees.

Given that I can see the size of the array when it fails (usually somewhere between 3000 and 5000 instances) and the size of the TreeInstance struct (20 floats), I'm sure my problem lies not in the raw size of the array. Even considering that it has to be temporarily doubled during the resize/8 process (since Array.Resize() allocates a new array) that's still less than half a MB assuming my math is right.

I assume therefore that there must be something I'm missing. Is there some reason the old arrays might not be removed by the garbage collector?

Further Details:

  • TreeInstance is a simple struct, with the transform matrix and colour of each tree.
  • treeInstances is a TreeInstance[] array. It is only used directly here, in the lines of code above.
  • treeInstances also has a Property, TreeInstances, which accesses it via get;set;
  • TreeInstances is used to set the transform matrix and colour of each tree as it grows, and is fed into the Instancing methods as part of the Draw routine.
  • The Instancing methods I'm less familiar with, but perform a variety of functions with TreeInstances without modifying it's contents (including using it as the source in a DynamicVertexBuffer.SetData operation).
like image 439
Quasar Avatar asked Jan 30 '26 13:01

Quasar


1 Answers

C# is designed to handle small memory allocation much better than large ones. When you do an Array.Resize you are forcing a new memory block to be allocated, the data copied then the old block invalidated. It is a very effective algorithm for fragmenting your heap :-)

If you know how large your array needs to be at the start, make your array that size. If you don't I suggest you use List or a similar class. That class allocates on a per item basis.

I stand corrected, thanks guys for keeping me honest. I'm too use to dealing with classes rather than structs. I should have been more awake.

If TreeInstance is changed to a class, then List becomes and array of addresses and the TreeInstance's can/will be allocated in smaller chunks. Some code changes will be required to new up all the TreeInstance's.

like image 115
Dweeberly Avatar answered Feb 02 '26 04:02

Dweeberly



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!