Skip to content

Commit

Permalink
RavenDB-23704 - Move allocation pointer back when releasing memory at…
Browse files Browse the repository at this point in the history
… current allocation boundary
  • Loading branch information
grisha-kotler committed Mar 5, 2025
1 parent 946de66 commit 3a6b940
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 2 deletions.
6 changes: 5 additions & 1 deletion src/Sparrow.Server/ByteString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1336,7 +1336,11 @@ public void Release(ref ByteString value)

int reusablePoolIndex = GetPoolIndexForReuse(value._pointer->Size);

if (value._pointer->Size <= ByteStringContext.MinBlockSizeInBytes)
if (value._pointer == _internalCurrent.Current - value._pointer->Size)
{
_internalCurrent.Current -= value._pointer->Size;
}
else if (value._pointer->Size <= ByteStringContext.MinBlockSizeInBytes)
{
FastStack<IntPtr> pool = _internalReusableStringPool[reusablePoolIndex];
if (pool == null)
Expand Down
34 changes: 33 additions & 1 deletion test/FastTests/Sparrow/ByteStringTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using Sparrow.Global;
using Sparrow.Server;
using Sparrow.Threading;
using Tests.Infrastructure;
Expand Down Expand Up @@ -195,6 +195,38 @@ public void CanResetAllocationBlockSize()
}
}

[RavenFact(RavenTestCategory.Memory)]
public void CanReuseMemory()
{
using (var context = new ByteStringContext<ByteStringDirectAllocator>(SharedMultipleUseFlag.None))
{
while (context.AllocationBlockSize != 2 * Constants.Size.Megabyte)
{
context.Allocate(ByteStringContext.MinBlockSizeInBytes / 2, out _);
}

Assert.Equal(2 * Constants.Size.Megabyte, context.AllocationBlockSize);

const int toAllocate = ByteStringContext.MinBlockSizeInBytes * 5;
context.Allocate(toAllocate, out var first);
var ptrLocation = (long)first._pointer;
var allocatedBefore = context._totalAllocated;
context.Release(ref first);

for (var i = 0; i < 512; i++)
{
var allocation = i % 2 == 0 ? toAllocate / 2 : toAllocate;
context.Allocate(allocation, out var byteString);

Assert.Equal(ptrLocation, (long)byteString._pointer);

context.Release(ref byteString);
}

Assert.Equal(allocatedBefore, context._totalAllocated);
}
}

#if VALIDATE
[Fact]
public void ValidationKeyAfterAllocateAndReleaseReuseShouldBeDifferent()
Expand Down

0 comments on commit 3a6b940

Please sign in to comment.