diff --git a/src/ImageSharp/Memory/PixelDataPool{T}.cs b/src/ImageSharp/Memory/PixelDataPool{T}.cs
index f25803951..80c9c410e 100644
--- a/src/ImageSharp/Memory/PixelDataPool{T}.cs
+++ b/src/ImageSharp/Memory/PixelDataPool{T}.cs
@@ -17,17 +17,32 @@ namespace SixLabors.ImageSharp.Memory
/// The maximum size of pooled arrays in bytes.
/// Currently set to 32MB, which is equivalent to 8 megapixels of raw data.
///
- private const int MaxPooledBufferSizeInBytes = 32 * 1024 * 1024;
+ internal const int MaxPooledBufferSizeInBytes = 32 * 1024 * 1024;
///
- /// The maximum array length of the .
+ /// The threshold to pool arrays in which has less buckets for memory safety.
///
- private static readonly int MaxArrayLength = MaxPooledBufferSizeInBytes / Unsafe.SizeOf();
+ private const int LargeBufferThresholdInBytes = 8 * 1024 * 1024;
///
- /// The which is not kept clean.
+ /// The maximum array length of the .
///
- private static readonly ArrayPool ArrayPool = ArrayPool.Create(MaxArrayLength, 50);
+ private static readonly int MaxLargeArrayLength = MaxPooledBufferSizeInBytes / Unsafe.SizeOf();
+
+ ///
+ /// The maximum array length of the .
+ ///
+ private static readonly int MaxNormalArrayLength = LargeBufferThresholdInBytes / Unsafe.SizeOf();
+
+ ///
+ /// The for huge buffers, which is not kept clean.
+ ///
+ private static readonly ArrayPool LargeArrayPool = ArrayPool.Create(MaxLargeArrayLength, 8);
+
+ ///
+ /// The for small-to-medium buffers which is not kept clean.
+ ///
+ private static readonly ArrayPool NormalArrayPool = ArrayPool.Create(MaxNormalArrayLength, 24);
///
/// Rents the pixel array from the pool.
@@ -36,7 +51,14 @@ namespace SixLabors.ImageSharp.Memory
/// The
public static T[] Rent(int minimumLength)
{
- return ArrayPool.Rent(minimumLength);
+ if (minimumLength <= MaxNormalArrayLength)
+ {
+ return NormalArrayPool.Rent(minimumLength);
+ }
+ else
+ {
+ return LargeArrayPool.Rent(minimumLength);
+ }
}
///
@@ -45,7 +67,14 @@ namespace SixLabors.ImageSharp.Memory
/// The array to return to the buffer pool.
public static void Return(T[] array)
{
- ArrayPool.Return(array);
+ if (array.Length <= MaxNormalArrayLength)
+ {
+ NormalArrayPool.Return(array);
+ }
+ else
+ {
+ LargeArrayPool.Return(array);
+ }
}
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Memory/PixelDataPoolTests.cs b/tests/ImageSharp.Tests/Memory/PixelDataPoolTests.cs
index beaa49dbc..caba9a464 100644
--- a/tests/ImageSharp.Tests/Memory/PixelDataPoolTests.cs
+++ b/tests/ImageSharp.Tests/Memory/PixelDataPoolTests.cs
@@ -9,19 +9,25 @@ using Xunit;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests.Memory
{
+ using System;
+
///
/// Tests the class.
///
public class PixelDataPoolTests
{
+ private const int MaxPooledBufferSizeInBytes = PixelDataPool.MaxPooledBufferSizeInBytes;
+
readonly object monitor = new object();
- [Fact]
- public void PixelDataPoolRentsMinimumSize()
+ [Theory]
+ [InlineData(1)]
+ [InlineData(1024)]
+ public void PixelDataPoolRentsMinimumSize(int size)
{
- Rgba32[] pixels = PixelDataPool.Rent(1024);
+ Rgba32[] pixels = PixelDataPool.Rent(size);
- Assert.True(pixels.Length >= 1024);
+ Assert.True(pixels.Length >= size);
}
[Fact]
@@ -65,17 +71,21 @@ namespace SixLabors.ImageSharp.Tests.Memory
}
}
- [Fact]
- public void SmallBuffersArePooled()
+ [Theory]
+ [InlineData(32)]
+ [InlineData(512)]
+ [InlineData(MaxPooledBufferSizeInBytes-1)]
+ public void SmallBuffersArePooled(int size)
{
- Assert.True(this.CheckIsPooled(5, 512));
+ Assert.True(this.CheckIsPooled(5, size));
}
- [Fact]
- public void LargeBuffersAreNotPooled_OfByte()
+ [Theory]
+ [InlineData(128 * 1024 * 1024)]
+ [InlineData(MaxPooledBufferSizeInBytes+1)]
+ public void LargeBuffersAreNotPooled_OfByte(int size)
{
- const int mb128 = 128 * 1024 * 1024;
- Assert.False(this.CheckIsPooled(2, mb128));
+ Assert.False(this.CheckIsPooled(2, size));
}
[StructLayout(LayoutKind.Explicit, Size = 512)]