-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Add ArraySegmentPool #41240
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @tannergooding, @pgovind |
@wizardars you need to propose an API. Here's an example of an API proposal #41118 or #41191. Also ArraySegment<T> is basically legacy at this point, replaced by Memory<T> |
Eh, I wouldn't go quite that far. It's true that we're adding |
I would never use ArraySegment<T> in a new API. It's leaky abstraction at best and hardly anything uses it today in the BCL (good think it's convertible to Memory<T> and Span<T>) |
@davidfowl We do not have a template for the proposed implementations, so I improvised. |
You don't need the implementation until the issue just the public API surface. Memory is a replacement for ArraySegment and you can get at the Array (if it happens to be backed by one). Can you explain why this API is needed in the BCL? Why can't this just exist in your project? |
Since ArraySegment just wraps an array, couldn't you just use |
Your tests don't demonstrate that using a pool yields a benefit (no comparison with no pool). The preferred way to set these up is to use something like Benchmarkdotnet (which is what most of the code here uses). Also, none of this code actually pools |
@davidfowl I think the reason is the same as for the ArrayPool and other tools.
|
@FiniteReality I think not. ArrayPool and ArraySegmentPool are completely different. ArrayPool for arrays and ArraySegmentPool for array segments. |
@Clockwork-Muse ArraySegmentPool is not an improved version of ArrayPool, it is a completely different tool. I don't know how to compare ArraySegment without the pool, because ArraySegment it's just a segment of array. So w/o array segment can't exist. Actually, an array is a pool for a segment, but without the convenient management that a ArraySegmentPool provides. |
@wizardars - Taking that list:
There aren't many (any?) alternatives, because people were probably pooling the arrays (even before var pooled = GetArrayFromPool();
var segment = new ArraySegment(pooled); .... and once you had that segment, most of the code down that stack would be focused on working with that single segment by slicing it, not needing to go back to a pool (contrast with working with raw arrays, where you should be hitting a pool each time, or And that's the problem, actually. Across API boundaries, you should be using |
@Clockwork-Muse Thank you for the discussion, but I did not understand which scenario you are describing and what exactly you think about adding a pool to the BCL. |
I am not in favor of adding this pool, because it doesn't provide a significant enhancement to what was possible before. At best, this pool turns two lines into one, and that rarely. If I was interfacing with APIs that took |
@Clockwork-Muse Thank you for doing such a job and comparing the speed. I will be extremely grateful to you if you attach your test here). |
.... what exactly are you expecting me to compare here? Using This file has the performance tests for |
I think that a better solution would be to extend the already existing Such efficient implementation that could be used for Because such a managed manual memory manager seems meaningless and inefficient, value types with no references could use unmanaged memory with User-created memory pools can use a fixed-size implementation like the one @wizardars proposed. Two different implementations also exist between the shared and custom array pools. |
The class is abstract, so the intention is that other types can be created. Including something that interfaces with unmanaged memory (... at which point it becomes managed by the implementing class....) In the majority case, though, just using the default memory/array pool is going to be way more than sufficient (and may perform better in some scenarios), because an array is going to take (almost) the same amount of space both managed and "unmanaged". There may be cases that need to be working over native/device memory, and want to pool it (say, GPU buffers), but these are either going to be one-offs unique to that library, or a common library used by an extremely small subset of all Nuget packages. That is, not something we would design/build. |
Thanks for the suggestion. We're not going to add a pool dedicated to ArraySegment. ArrayPool suffices for that, since a segment is just a tuple of an array, offset, and length. |
Background and Motivation
This pool will be necessary for developers who do not agree to compromise and want to write the fastest solutions. For example, protocols with zero allocations over UDP with a bandwidth of more than 1 gigabit .
Implementation explanation
Pool for ArraySegments.
Features:
Model:
Usage Examples
Initialize (Auto resize mode)
Initialize (Fixed size mode)
Rent
Return
Alternative Designs
No other options.
Risks
The ArraySegment will be modified and size will be increased by 1 byte.
https://github.com/dotnet/runtime/pull/41237/files#diff-aa8a8894d7639b5648acaf9aac2a36c4
Proposed implementation
source.zip
Proposed test
https://github.com/wizardars/test
The text was updated successfully, but these errors were encountered: