To try minimize garbage collection, I profiled my application and found out the following property.
Naturally, I decided to give a try in using a shared pool.
Not only that didn't work out at all, but the memory usage bloated in the mean time:
Self (Allocations) | Self Size (Bytes) |
---|---|
3,848 | 3,293,888 |
21,098 | 70,720,496 |
partial class ImDrawData
{
private ImDrawList[]? CmdListsArray;
public unsafe ImDrawList[] CmdLists
{
get
{
var pool = ArrayPool<ImDrawList>.Shared;
if (CmdListsArray != null)
{
pool.Return(CmdListsArray);
}
var size = CmdListsCount;
var rent = CmdListsArray = pool.Rent(size);
var data = (IntPtr*)((__Internal*)__Instance)->CmdLists;
for (var i = 0; i < size; i )
{
rent[i] = ImDrawList.__CreateInstance(data[i]);
}
return rent;
}
}
}
The original code would simply create a new array each time the property was queried.
Question:
How can I implement an effective array pool for that particular property?
CodePudding user response:
I ended up fixing the problem with a good old C-like approach:
The consumer is now responsible about passing the array.
public unsafe int GetCmdLists([NotNull] ref ImDrawList[]? lists)
{
var count = CmdListsCount;
if (lists is null || lists.Length < count)
{
Array.Resize(ref lists, count);
}
var input = (IntPtr*)((__Internal*)__Instance)->CmdLists;
for (var i = 0; i < count; i )
{
lists[i] = ImDrawList.__CreateInstance(input[i]);
}
return count;
}
By allocating a sufficiently large array for common use, I now get zero reallocations and zero GC.