From a8273901c196c33f500d60532c85292ef5412418 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 25 Nov 2021 14:17:19 +0100 Subject: [PATCH] Docs and null check on Configuration.MemoryAllocator. --- src/ImageSharp/Configuration.cs | 31 +++++++++++++++++--- tests/ImageSharp.Tests/ConfigurationTests.cs | 15 ++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) 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() {