diff --git a/cs/src/core/Utilities/BufferPool.cs b/cs/src/core/Utilities/BufferPool.cs
index ae064ef83..525581eed 100644
--- a/cs/src/core/Utilities/BufferPool.cs
+++ b/cs/src/core/Utilities/BufferPool.cs
@@ -123,10 +123,18 @@ public override string ToString()
public sealed class SectorAlignedBufferPool
{
///
- /// Disable buffer pool
+ /// Disable buffer pool.
+ /// This static option should be enabled on program entry, and not modified once FASTER is instantiated.
///
public static bool Disabled = false;
+ ///
+ /// Unpin objects when they are returned to the pool, so that we do not hold pinned objects long term.
+ /// If set, we will unpin when objects are returned and re-pin when objects are returned from the pool.
+ /// This static option should be enabled on program entry, and not modified once FASTER is instantiated.
+ ///
+ public static bool UnpinOnReturn = false;
+
private const int levels = 32;
private readonly int recordSize;
private readonly int sectorSize;
@@ -164,7 +172,14 @@ public void Return(SectorAlignedMemory page)
page.valid_offset = 0;
Array.Clear(page.buffer, 0, page.buffer.Length);
if (!Disabled)
+ {
+ if (UnpinOnReturn)
+ {
+ page.handle.Free();
+ page.handle = default;
+ }
queue[page.level].Enqueue(page);
+ }
else
{
page.handle.Free();
@@ -210,6 +225,12 @@ public unsafe SectorAlignedMemory Get(int numRecords)
if (!Disabled && queue[index].TryDequeue(out SectorAlignedMemory page))
{
+ if (UnpinOnReturn)
+ {
+ page.handle = GCHandle.Alloc(page.buffer, GCHandleType.Pinned);
+ page.aligned_pointer = (byte*)(((long)page.handle.AddrOfPinnedObject() + (sectorSize - 1)) & ~((long)sectorSize - 1));
+ page.offset = (int)((long)page.aligned_pointer - (long)page.handle.AddrOfPinnedObject());
+ }
return page;
}
@@ -239,7 +260,8 @@ public void Free()
if (queue[i] == null) continue;
while (queue[i].TryDequeue(out SectorAlignedMemory result))
{
- result.handle.Free();
+ if (!UnpinOnReturn)
+ result.handle.Free();
result.buffer = null;
}
}