Browse Source

tuning ArrayPoolMemoryManager configuration based on benchmark results

af/merge-core
Anton Firszov 8 years ago
parent
commit
c1b4707113
  1. 2
      src/ImageSharp/Configuration.cs
  2. 17
      src/ImageSharp/Memory/ArrayPoolMemoryManager.Buffer{T}.cs
  3. 33
      src/ImageSharp/Memory/ArrayPoolMemoryManager.CommonFactoryMethods.cs
  4. 3
      src/ImageSharp/Memory/ArrayPoolMemoryManager.cs
  5. 2
      src/ImageSharp/Memory/IManagedByteBuffer.cs
  6. 6
      src/ImageSharp/Memory/MemoryManager.cs

2
src/ImageSharp/Configuration.cs

@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Gets or sets the <see cref="MemoryManager"/> that is currently in use.
/// </summary>
public MemoryManager MemoryManager { get; set; } = ArrayPoolMemoryManager.CreateWithNormalPooling();
public MemoryManager MemoryManager { get; set; } = ArrayPoolMemoryManager.CreateDefault();
/// <summary>
/// Gets the maximum header size of all the formats.

17
src/ImageSharp/Memory/ArrayPoolMemoryManager.Buffer{T}.cs

@ -11,11 +11,20 @@ namespace SixLabors.ImageSharp.Memory
/// </summary>
public partial class ArrayPoolMemoryManager
{
/// <summary>
/// The buffer implementation of <see cref="ArrayPoolMemoryManager"/>
/// </summary>
private class Buffer<T> : IBuffer<T>
where T : struct
{
/// <summary>
/// The length of the buffer
/// </summary>
private readonly int length;
/// <summary>
/// A weak reference to the source pool.
/// </summary>
private WeakReference<ArrayPool<byte>> sourcePoolReference;
public Buffer(byte[] data, int length, ArrayPool<byte> sourcePool)
@ -25,10 +34,15 @@ namespace SixLabors.ImageSharp.Memory
this.sourcePoolReference = new WeakReference<ArrayPool<byte>>(sourcePool);
}
/// <summary>
/// Gets the buffer as a byte array.
/// </summary>
protected byte[] Data { get; private set; }
/// <inheritdoc />
public Span<T> Span => this.Data.AsSpan().NonPortableCast<byte, T>().Slice(0, this.length);
/// <inheritdoc />
public void Dispose()
{
if (this.Data == null || this.sourcePoolReference == null)
@ -46,6 +60,9 @@ namespace SixLabors.ImageSharp.Memory
}
}
/// <summary>
/// The <see cref="IManagedByteBuffer"/> implementation of <see cref="ArrayPoolMemoryManager"/>.
/// </summary>
private class ManagedByteBuffer : Buffer<byte>, IManagedByteBuffer
{
public ManagedByteBuffer(byte[] data, int length, ArrayPool<byte> sourcePool)

33
src/ImageSharp/Memory/ArrayPoolMemoryManager.CommonFactoryMethods.cs

@ -7,22 +7,36 @@
{
/// <summary>
/// The default value for: maximum size of pooled arrays in bytes.
/// Currently set to 32MB, which is equivalent to 8 megapixels of raw <see cref="Rgba32"/> data.
/// Currently set to 24MB, which is equivalent to 8 megapixels of raw <see cref="Rgba32"/> data.
/// </summary>
internal const int DefaultMaxPooledBufferSizeInBytes = 32 * 1024 * 1024;
internal const int DefaultMaxPooledBufferSizeInBytes = 24 * 1024 * 1024;
/// <summary>
/// The value for: The threshold to pool arrays in <see cref="largeArrayPool"/> which has less buckets for memory safety.
/// </summary>
private const int DefaultBufferSelectorThresholdInBytes = 8 * 1024 * 1024;
/// <summary>
/// The default bucket count for <see cref="largeArrayPool"/>.
/// </summary>
private const int DefaultLargePoolBucketCount = 6;
/// <summary>
/// The default bucket count for <see cref="normalArrayPool"/>.
/// </summary>
private const int DefaultNormalPoolBucketCount = 16;
/// <summary>
/// This is the default. Should be good for most use cases.
/// </summary>
/// <returns>The memory manager</returns>
public static ArrayPoolMemoryManager CreateWithNormalPooling()
public static ArrayPoolMemoryManager CreateDefault()
{
return new ArrayPoolMemoryManager(DefaultMaxPooledBufferSizeInBytes, DefaultBufferSelectorThresholdInBytes, 8, 24);
return new ArrayPoolMemoryManager(
DefaultMaxPooledBufferSizeInBytes,
DefaultBufferSelectorThresholdInBytes,
DefaultLargePoolBucketCount,
DefaultNormalPoolBucketCount);
}
/// <summary>
@ -31,7 +45,16 @@
/// <returns>The memory manager</returns>
public static ArrayPoolMemoryManager CreateWithModeratePooling()
{
return new ArrayPoolMemoryManager(1024 * 1024, 1024 * 16, 16, 24);
return new ArrayPoolMemoryManager(1024 * 1024, 32 * 1024, 16, 24);
}
/// <summary>
/// Only pool small buffers like image rows.
/// </summary>
/// <returns>The memory manager</returns>
public static ArrayPoolMemoryManager CreateWithMinimalPooling()
{
return new ArrayPoolMemoryManager(64 * 1024, 32 * 1024, 8, 24);
}
/// <summary>

3
src/ImageSharp/Memory/ArrayPoolMemoryManager.cs

@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Memory
/// <param name="maxPoolSizeInBytes">The maximum size of pooled arrays. Arrays over the thershold are gonna be always allocated.</param>
/// <param name="poolSelectorThresholdInBytes">Arrays over this threshold will be pooled in <see cref="largeArrayPool"/> which has less buckets for memory safety.</param>
public ArrayPoolMemoryManager(int maxPoolSizeInBytes, int poolSelectorThresholdInBytes)
: this(maxPoolSizeInBytes, poolSelectorThresholdInBytes, 8, 24)
: this(maxPoolSizeInBytes, poolSelectorThresholdInBytes, DefaultLargePoolBucketCount, DefaultNormalPoolBucketCount)
{
}
@ -106,6 +106,7 @@ namespace SixLabors.ImageSharp.Memory
return buffer;
}
/// <inheritdoc />
internal override IManagedByteBuffer AllocateManagedByteBuffer(int length, bool clear)
{
ArrayPool<byte> pool = this.GetArrayPool(length);

2
src/ImageSharp/Memory/IManagedByteBuffer.cs

@ -4,7 +4,7 @@
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Represents a byte buffer backed by a managed array.
/// Represents a byte buffer backed by a managed array. Useful for interop with classic .NET API-s.
/// </summary>
internal interface IManagedByteBuffer : IBuffer<byte>
{

6
src/ImageSharp/Memory/MemoryManager.cs

@ -19,6 +19,12 @@ namespace SixLabors.ImageSharp.Memory
internal abstract IBuffer<T> Allocate<T>(int length, bool clear)
where T : struct;
/// <summary>
/// Allocates an <see cref="IManagedByteBuffer"/>
/// </summary>
/// <param name="length">The requested buffer length</param>
/// <param name="clear">A value indicating whether to clean the buffer</param>
/// <returns>The <see cref="IManagedByteBuffer"/></returns>
internal abstract IManagedByteBuffer AllocateManagedByteBuffer(int length, bool clear);
/// <summary>

Loading…
Cancel
Save