From 3b3e8a0d6cc9a90520b1bbe23406b8d428e38e8f Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 5 Feb 2020 13:44:59 +1100 Subject: [PATCH] Reduce captuing allocation to 16 bytes. --- .../Advanced/ParallelUtils/IRowAction.cs | 37 ---------- .../ParallelUtils/IRowIntervalAction.cs | 68 +++++++++++++++++++ .../Advanced/ParallelUtils/ParallelHelper.cs | 24 ++----- .../Transforms/CropProcessor{TPixel}.cs | 14 +--- 4 files changed, 74 insertions(+), 69 deletions(-) delete mode 100644 src/ImageSharp/Advanced/ParallelUtils/IRowAction.cs create mode 100644 src/ImageSharp/Advanced/ParallelUtils/IRowIntervalAction.cs diff --git a/src/ImageSharp/Advanced/ParallelUtils/IRowAction.cs b/src/ImageSharp/Advanced/ParallelUtils/IRowAction.cs deleted file mode 100644 index a0fd2aaf21..0000000000 --- a/src/ImageSharp/Advanced/ParallelUtils/IRowAction.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Runtime.CompilerServices; -using SixLabors.ImageSharp.Memory; - -namespace SixLabors.ImageSharp.Advanced.ParallelUtils -{ - /// - /// Defines the contract for. - /// - public interface IRowAction - { - /// - /// Invokes the method passing the row interval. - /// - /// The row interval. - void Invoke(in RowInterval rows); - } - - internal readonly struct WrappingRowAction : IRowAction - where T : struct, IRowAction - { - private readonly T action; - - public WrappingRowAction(ref T action) - { - this.action = action; - } - - [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(in RowInterval rows) - { - this.action.Invoke(in rows); - } - } -} diff --git a/src/ImageSharp/Advanced/ParallelUtils/IRowIntervalAction.cs b/src/ImageSharp/Advanced/ParallelUtils/IRowIntervalAction.cs new file mode 100644 index 0000000000..b178434ce0 --- /dev/null +++ b/src/ImageSharp/Advanced/ParallelUtils/IRowIntervalAction.cs @@ -0,0 +1,68 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; +using SixLabors.ImageSharp.Memory; + +namespace SixLabors.ImageSharp.Advanced.ParallelUtils +{ + /// + /// Defines the contract for. + /// + public interface IRowIntervalAction + { + /// + /// Invokes the method passing the row interval. + /// + /// The row interval. + void Invoke(in RowInterval rows); + } + + internal readonly struct WrappingRowIntervalInfo + { + public readonly int Min; + public readonly int Max; + public readonly int Step; + + public WrappingRowIntervalInfo(int min, int max, int step) + { + this.Min = min; + this.Max = max; + this.Step = step; + } + } + + internal readonly struct WrappingRowIntervalAction : IRowIntervalAction + where T : struct, IRowIntervalAction + { + private readonly WrappingRowIntervalInfo info; + private readonly T action; + + public WrappingRowIntervalAction(in WrappingRowIntervalInfo info, ref T action) + { + this.info = info; + this.action = action; + } + + [MethodImpl(InliningOptions.ShortMethod)] + public void Invoke(int i) + { + int yMin = this.info.Min + (i * this.info.Step); + + if (yMin >= this.info.Max) + { + return; + } + + int yMax = Math.Min(yMin + this.info.Step, this.info.Max); + + var rows = new RowInterval(yMin, yMax); + + this.Invoke(in rows); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public void Invoke(in RowInterval rows) => this.action.Invoke(in rows); + } +} diff --git a/src/ImageSharp/Advanced/ParallelUtils/ParallelHelper.cs b/src/ImageSharp/Advanced/ParallelUtils/ParallelHelper.cs index 1be8a638da..58f3169d1c 100644 --- a/src/ImageSharp/Advanced/ParallelUtils/ParallelHelper.cs +++ b/src/ImageSharp/Advanced/ParallelUtils/ParallelHelper.cs @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Advanced.ParallelUtils /// The to get the parallel settings from. /// The method body defining the iteration logic on a single . public static void IterateRowsFast(Rectangle rectangle, Configuration configuration, ref T body) - where T : struct, IRowAction + where T : struct, IRowIntervalAction { var parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration); @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Advanced.ParallelUtils Rectangle rectangle, in ParallelExecutionSettings parallelSettings, ref T body) - where T : struct, IRowAction + where T : struct, IRowIntervalAction { ValidateRectangle(rectangle); @@ -74,28 +74,14 @@ namespace SixLabors.ImageSharp.Advanced.ParallelUtils int top = rectangle.Top; int bottom = rectangle.Bottom; - - var rowAction = new WrappingRowAction(ref body); + var rowInfo = new WrappingRowIntervalInfo(top, bottom, verticalStep); + var rowAction = new WrappingRowIntervalAction(in rowInfo, ref body); Parallel.For( 0, numOfSteps, parallelOptions, - i => - { - int yMin = top + (i * verticalStep); - - if (yMin >= bottom) - { - return; - } - - int yMax = Math.Min(yMin + verticalStep, bottom); - - var rows = new RowInterval(yMin, yMax); - - rowAction.Invoke(in rows); - }); + i => rowAction.Invoke(i)); } /// diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs index ec78ba1711..59ef75b6ee 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs @@ -52,18 +52,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms ParallelExecutionSettings parallelSettings = ParallelExecutionSettings.FromConfiguration(this.Configuration) .MultiplyMinimumPixelsPerTask(4); - // ParallelHelper.IterateRows( - // bounds, - // parallelSettings, - // rows => - // { - // for (int y = rows.Min; y < rows.Max; y++) - // { - // Span sourceRow = source.GetPixelRowSpan(y).Slice(bounds.Left); - // Span targetRow = destination.GetPixelRowSpan(y - bounds.Top); - // sourceRow.Slice(0, bounds.Width).CopyTo(targetRow); - // } - // }); var rowAction = new RowAction(ref bounds, source, destination); ParallelHelper.IterateRowsFast( @@ -72,7 +60,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms ref rowAction); } - private readonly struct RowAction : IRowAction + private readonly struct RowAction : IRowIntervalAction { private readonly Rectangle bounds; private readonly ImageFrame source;