Browse Source

Reduce captuing allocation to 16 bytes.

af/octree-no-pixelmap
James Jackson-South 6 years ago
parent
commit
3b3e8a0d6c
  1. 37
      src/ImageSharp/Advanced/ParallelUtils/IRowAction.cs
  2. 68
      src/ImageSharp/Advanced/ParallelUtils/IRowIntervalAction.cs
  3. 24
      src/ImageSharp/Advanced/ParallelUtils/ParallelHelper.cs
  4. 14
      src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs

37
src/ImageSharp/Advanced/ParallelUtils/IRowAction.cs

@ -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
{
/// <summary>
/// Defines the contract for.
/// </summary>
public interface IRowAction
{
/// <summary>
/// Invokes the method passing the row interval.
/// </summary>
/// <param name="rows">The row interval.</param>
void Invoke(in RowInterval rows);
}
internal readonly struct WrappingRowAction<T> : 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);
}
}
}

68
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
{
/// <summary>
/// Defines the contract for.
/// </summary>
public interface IRowIntervalAction
{
/// <summary>
/// Invokes the method passing the row interval.
/// </summary>
/// <param name="rows">The row interval.</param>
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<T> : 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);
}
}

24
src/ImageSharp/Advanced/ParallelUtils/ParallelHelper.cs

@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Advanced.ParallelUtils
/// <param name="configuration">The <see cref="Configuration"/> to get the parallel settings from.</param>
/// <param name="body">The method body defining the iteration logic on a single <see cref="RowInterval"/>.</param>
public static void IterateRowsFast<T>(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<T>(ref body);
var rowInfo = new WrappingRowIntervalInfo(top, bottom, verticalStep);
var rowAction = new WrappingRowIntervalAction<T>(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));
}
/// <summary>

14
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<TPixel> sourceRow = source.GetPixelRowSpan(y).Slice(bounds.Left);
// Span<TPixel> 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<TPixel> source;

Loading…
Cancel
Save