From 7c1f05b0a8aebad8a5515cb8c5c42780b0fc9a22 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sun, 21 Nov 2021 11:28:02 +0100 Subject: [PATCH] Avoid allocating too many CostInterval objects --- .../Formats/Webp/Lossless/CostManager.cs | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/ImageSharp/Formats/Webp/Lossless/CostManager.cs b/src/ImageSharp/Formats/Webp/Lossless/CostManager.cs index 94c7bd8470..213971764b 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/CostManager.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/CostManager.cs @@ -14,6 +14,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless { private CostInterval head; + private const int FreeIntervalsStartCount = 25; + + private readonly Stack freeIntervals = new(FreeIntervalsStartCount); + public CostManager(ushort[] distArray, int pixCount, CostModel costModel) { int costCacheSize = pixCount > BackwardReferenceEncoder.MaxLength ? BackwardReferenceEncoder.MaxLength : pixCount; @@ -24,6 +28,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless this.DistArray = distArray; this.Count = 0; + for (int i = 0; i < FreeIntervalsStartCount; i++) + { + this.freeIntervals.Push(new CostInterval()); + } + // Fill in the cost cache. this.CacheIntervalsSize++; this.CostCache.Add(costModel.GetLengthCost(0)); @@ -201,10 +210,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless this.InsertInterval(interval, interval.Cost, interval.Index, end, endOriginal); break; } - else - { - interval.End = start; - } + + interval.End = start; } } @@ -226,6 +233,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless this.ConnectIntervals(interval.Previous, interval.Next); this.Count--; + + interval.Next = null; + interval.Previous = null; + this.freeIntervals.Push(interval); } private void InsertInterval(CostInterval intervalIn, float cost, int position, int start, int end) @@ -236,13 +247,19 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } // TODO: should we use COST_CACHE_INTERVAL_SIZE_MAX? - var intervalNew = new CostInterval() + CostInterval intervalNew; + if (this.freeIntervals.Count > 0) { - Cost = cost, - Start = start, - End = end, - Index = position - }; + intervalNew = this.freeIntervals.Pop(); + intervalNew.Cost = cost; + intervalNew.Start = start; + intervalNew.End = end; + intervalNew.Index = position; + } + else + { + intervalNew = new CostInterval() { Cost = cost, Start = start, End = end, Index = position }; + } this.PositionOrphanInterval(intervalNew, intervalIn); this.Count++;