-
Notifications
You must be signed in to change notification settings - Fork 414
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
Batch
overloads using an array pool
#856
Conversation
Here are some initial benchmarks:
The benchmark code was as follows: using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
using MoreLinq;
using MoreLinq.Experimental;
_ = BenchmarkRunner.Run<Benchmarks>();
[SimpleJob(RuntimeMoniker.Net60)]
[MemoryDiagnoser]
public class Benchmarks
{
[Params(1_000, 10_000, 100_000)]
public int Size { get; set; }
[Benchmark]
public void BatchRegular()
{
MoreEnumerable
.Generate(1L, x => x + 1)
.Take(1_000_000)
.Batch(Size)
.Select(Enumerable.Sum)
.Consume();
}
[Benchmark]
public void BatchPooled()
{
MoreEnumerable
.Generate(1L, x => x + 1)
.Take(1_000_000)
.Batch(Size, ArrayPool<long>.Shared, Enumerable.Sum)
.Consume();
}
} |
Codecov Report
@@ Coverage Diff @@
## master #856 +/- ##
=======================================
Coverage 92.45% 92.45%
=======================================
Files 108 108
Lines 3434 3434
Branches 1025 1025
=======================================
Hits 3175 3175
Misses 197 197
Partials 62 62 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
These changes belonged with: > commit 61dbc84 > Author: Atif Aziz <[email protected]> > Date: Sat Oct 29 19:11:45 2022 +0200 > > Remove "AsSpan" from current list
Co-authored-by: Stuart Turner <[email protected]>
Co-authored-by: Stuart Turner <[email protected]>
Co-authored-by: Stuart Turner <[email protected]>
This PR adds
Batch
overloads using an array pool. It provides an alternative approach to PR #833 by @leandromoh.The new overloads accept an
ArrayPool<>
argument, which is then used to rent an array to back each bucket. The rented array is returned to the pool before proceeding with the next bucket, for which a new rental is made. Chances are good that the same array ends up backing each bucket.The overloads also introduce
ICurrentBuffer<T>
, which is effectively aIList<T>
but one that gets updated in-place, thus bringing some notion of currency. AnICurrentBuffer<T>
is only valid during aBatch
operation and is never meant to escape or be used outside of the invocation (via side-effects). Doing so will lead to undefined behaviour. The reason for not using a plainIList<T>
is to make all this painfully obvious through the signatures.In terms of usage, it's fairly straightforward. Suppose the following use of
Batch
(regular, non-pooled) to sum a million numbers in chunks of 10,000:The same can be done with the new
Batch
as follows:The first version will allocate 100 arrays whereas the second one should use a single array.
PS These
Batch
overloads are considered experimental.