-
-
Notifications
You must be signed in to change notification settings - Fork 853
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove Closure Allocations when Iterating Rows in Parallel #1107
Remove Closure Allocations when Iterating Rows in Parallel #1107
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1107 +/- ##
==========================================
- Coverage 82.23% 82.04% -0.19%
==========================================
Files 702 700 -2
Lines 29163 28883 -280
Branches 3297 3286 -11
==========================================
- Hits 23981 23698 -283
- Misses 4491 4497 +6
+ Partials 691 688 -3
Continue to review full report at Codecov.
|
…delegate WIP: single row value delegates for parallel iterator
3... 2... 1... 😉 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few wishes regarding naming of internals I find misleading at the moment, otherwise LGTM.
} | ||
} | ||
|
||
private readonly struct WrappingRowIntervalOperation<T> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be RowIntervalOperationWrapper<T>
instead? Took me a a while to figure out it is exactly the opposite as it's name :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha, yeah no problem.
/// </content> | ||
public static partial class ParallelRowIterator | ||
{ | ||
private readonly struct WrappingRowIntervalInfo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This deserves a better name. IterationParameters
maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with that, will update.
public readonly int MinY; | ||
public readonly int MaxY; | ||
public readonly int StepY; | ||
public readonly int MaxX; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be Width
instead? First I thought there is a bug, and we are actually allocating a buffer with the size defined by the maximum x
coordinate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me.
Prerequisites
Description
The way ImageSharp currently handles work-to-be-executed in parallel, at the simplest level, as a
Action<RowInterval>
. Any state necessary for the operation must therefore be provided as closures, incurring heap allocations.By utilizing a trick to exploit the reification in C# generics it's possible completely get rid of
callvirt
instructions when invoking a delegate passed as argument which, in turn, allows the compiler to inline the input delegate. This removes the closure allocations and importantly removes the risk of developers inadvertently passingthis
as an allocation.We can perform this optimization by updating the current
ParallelHelper.IterateRows
methods and variants to accept a readonly struct implementing an interface instead the current action. This optimization technique is already utilized within theIImageProcessor<TPixel>
API.The interface pattern is as follows.
And the methods as follows.
TODO