diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs
index 2c981c31b1..31c67dd687 100644
--- a/src/ImageSharp/Configuration.cs
+++ b/src/ImageSharp/Configuration.cs
@@ -26,10 +26,11 @@ namespace SixLabors.ImageSharp
///
/// A lazily initialized configuration default instance.
///
- private static readonly Lazy Lazy = new Lazy(CreateDefaultInstance);
+ private static readonly Lazy Lazy = new(CreateDefaultInstance);
private const int DefaultStreamProcessingBufferSize = 8096;
private int streamProcessingBufferSize = DefaultStreamProcessingBufferSize;
private int maxDegreeOfParallelism = Environment.ProcessorCount;
+ private MemoryAllocator memoryAllocator = MemoryAllocator.Default;
///
/// Initializes a new instance of the class.
@@ -125,9 +126,31 @@ namespace SixLabors.ImageSharp
public ImageFormatManager ImageFormatsManager { get; set; } = new ImageFormatManager();
///
- /// Gets or sets the that is currently in use.
+ /// Gets or sets the that is currently in use.
+ /// Defaults to .
+ ///
+ /// Allocators are expensive, so it is strongly recommended to use only one busy instance per process.
+ /// In case you need to customize it, you can ensure this by changing
///
- public MemoryAllocator MemoryAllocator { get; set; } = MemoryAllocator.Default;
+ ///
+ /// It's possible to reduce allocator footprint by assigning a custom instance created with
+ /// , but note that since the default pooling
+ /// allocators are expensive, it is strictly recommended to use a single process-wide allocator.
+ /// You can ensure this by altering the allocator of , or by implementing custom application logic that
+ /// manages allocator lifetime.
+ ///
+ /// If an allocator has to be dropped for some reason,
+ /// shall be invoked after disposing all associated instances.
+ ///
+ public MemoryAllocator MemoryAllocator
+ {
+ get => this.memoryAllocator;
+ set
+ {
+ Guard.NotNull(value, nameof(this.MemoryAllocator));
+ this.memoryAllocator = value;
+ }
+ }
///
/// Gets the maximum header size of all the formats.
@@ -173,7 +196,7 @@ namespace SixLabors.ImageSharp
MaxDegreeOfParallelism = this.MaxDegreeOfParallelism,
StreamProcessingBufferSize = this.StreamProcessingBufferSize,
ImageFormatsManager = this.ImageFormatsManager,
- MemoryAllocator = this.MemoryAllocator,
+ memoryAllocator = this.memoryAllocator,
ImageOperationsProvider = this.ImageOperationsProvider,
ReadOrigin = this.ReadOrigin,
FileSystem = this.FileSystem,
diff --git a/tests/ImageSharp.Tests/ConfigurationTests.cs b/tests/ImageSharp.Tests/ConfigurationTests.cs
index f77db33f06..bc2bf36b54 100644
--- a/tests/ImageSharp.Tests/ConfigurationTests.cs
+++ b/tests/ImageSharp.Tests/ConfigurationTests.cs
@@ -149,6 +149,21 @@ namespace SixLabors.ImageSharp.Tests
() => config.StreamProcessingBufferSize = 0);
}
+ [Fact]
+ public void MemoryAllocator_Setter_Roundtrips()
+ {
+ MemoryAllocator customAllocator = new SimpleGcMemoryAllocator();
+ var config = new Configuration() { MemoryAllocator = customAllocator };
+ Assert.Same(customAllocator, config.MemoryAllocator);
+ }
+
+ [Fact]
+ public void MemoryAllocator_SetNull_ThrowsArgumentNullException()
+ {
+ var config = new Configuration();
+ Assert.Throws(() => config.MemoryAllocator = null);
+ }
+
[Fact]
public void InheritsDefaultMemoryAllocatorInstance()
{