Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic Array Memory Allocation Strategies

Tags:

delphi

I've written a 32bit program using a dynamic array to store a list of triangles with an unknown count. My current strategy is to estimate a very large number of triangles and then trim the list when all the triangles are created. In some cases I'll only allocate memory once in others I'll need to add to the allocation.

With a very large data set I'm running out of memory when my application is memory usage is about 1.2GB and since the allocation step is so large I feel like I may be fragmenting memory.

Looking at FastMM (memory manager) I see these constants which would suggest one of these as a good size to increment by.

ChunkSize = 64 * 1024;
MaximumSmallBlockSize = 32752;
LargeBlockGranularity = 64 * 1024;

Would one of these be an optimal size for increasing the size of an array?

Eventually this program will become 64bit but we're not quite ready for that step.

like image 437
Mitch Avatar asked Sep 13 '26 01:09

Mitch


2 Answers

Your real problem here is not that you are running out of memory, but that the memory allocator cannot find a large enough block of contiguous address space. Some simple things you can do to help include:

  1. Execute the code in a 64 bit process.
  2. Add the LARGEADDRESSAWARE PE flag so that your process gets a 4GB address space rather than 2GB.

Beyond that the best you can do is allocate smaller blocks so that you avoid the requirement to store your large data structure in contiguous memory. Allocate memory in blocks. So, if you need 1GB of memory, allocate 64 blocks of size 16MB, for instance. The exact block size that you use can be tuned to your needs. Larger blocks result in better allocation performance, but smaller blocks allow you to use more address space.

Wrap this up in a container that presents an array like interface to the consumer, but internally stores the memory in non-contiguous blocks.

like image 87
David Heffernan Avatar answered Sep 16 '26 06:09

David Heffernan


As far as I know, dynamic arrays in Delphi use contiguous address space (at least in the virtual memory address space.)

Since you are running out of memory at 1.2 gb, I guess that's the point where the memory manager can't find a block contiguous memory large enough to fit a larger array.

One way you can work around this limitation would be to implement your array as a collection of smaller array of (lets say) 200 mb in size. That should give you some more headroom before you hit the memory cap.

From the 1.2 gb value, I would guess your program isn't compiled to be "large address aware". You can see here how to compile your application like this.

One last trick would be to actually save the array data in a file. I use this trick for one of my application where I needed to load a few GB of images to be displayed in a grid. What I did was to create a file with the attribute FILE_ATTRIBUTE_TEMPORARY and FILE_FLAG_DELETE_ON_CLOSE and saved/loaded images from the resulting file. From CreateFile documentation:

A file is being used for temporary storage. File systems avoid writing data back to mass storage if sufficient cache memory is available, because an application deletes a temporary file after a handle is closed. In that case, the system can entirely avoid writing the data. Otherwise, the data is written after the handle is closed.

Since it makes use of cache memory, I believe it allows an application to use memory beyond the 32 bits limitation since the cache is managed by the OS and (as far as I know) not mapped inside the process' virtual memory space. After doing this change, performance were still pretty good. But I can't say if performances would still be good enough for your needs.

like image 33
Ken Bourassa Avatar answered Sep 16 '26 06:09

Ken Bourassa