I am working on a physics simulation project where performance is critical, and I think one bottleneck is my memory management. Currently, I have buffer objects that contain a fixed number of rigid bodies, particles and forces. All of the physics entities are initialized within its buffer before the simulation starts. When an entity is needed, the first inactive one is selected, otherwise, the oldest, and when it is no longer needed, it is moved to the end, so the active entities are all front packed.
Here is the data structure that I am using.
public sealed class Buffer<TValue> : IEnumerable<BufferElement<TValue>> where TValue : new()
{
public Buffer(int capacity)
{
Count = 0;
Capacity = capacity;
Elements = new BufferElement<TValue>[capacity];
for (var index = 0; index < Elements.Length; index++)
{
Elements[index] = new BufferElement<TValue>();
}
}
public int Count { get; private set; }
public int Capacity { get; private set; }
private int ActiveCount { get; set; }
private BufferElement<TValue>[] Elements { get; }
public BufferElement<TValue> Activate()
{
if (Count == ActiveCount) Count = 0;
var bufferElement = Elements[Count++];
if (!bufferElement.Active)
{
bufferElement.Active = true;
ActiveCount++;
}
return bufferElement;
}
public void Deactivate(BufferElement element)
{
if (!element.Active) return;
element.Active = false;
var lhs = element.Index;
var rhs = --ActiveCount;
Elements[lhs] = Elements[rhs];
Elements[rhs] = element;
Elements[lhs].Index = lhs;
Elements[rhs].Index = rhs;
}
}
After reading up on how .NET Core treats arrays, there are two things that might be an issue. The first is each time you access an element in the array, it performs safety checks, and the second being that the GC can copy the array to a new memory address.
I would like to have all of my buffers that contain physics entities to not preform any safety checks and to be fixed in contiguous memory, if possible. I believe this should be possible, since the size of each buffer is fixed, and the size of the elements (rigid body, particle, force) are fixed as well.
There seems to be many ways of managing memory in C#, and I am having a difficult time figuring out which would be right for me in this situation.
Now, the question boils down to three parts:
- Can this be done?
- If so, what is the best method to manage memory?
- And, what would the proper implementation look like?