-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Modify segmented list to grow by growth rate. #75756
Modify segmented list to grow by growth rate. #75756
Conversation
A growth rate of 2x matches the current code behavior. A growth rate of just over 1 matches the growth rate (1 segment) in the other PR (dotnet#75708). All growth rates benchmarked: 1.000001, 1.1, 1.25, 1.5, 2 Obviously, the single segment growth rate is a non-starter without allowing null segments (which is the approach the other PR took). The 2x rate matches current behavior, and is really only measured as a baseline. From my reading of this chart, it looks like 1.1 is the best of these choices.
@@ -42,6 +42,8 @@ internal class SegmentedList<T> : IList<T>, IList, IReadOnlyList<T> | |||
private static readonly SegmentedArray<T> s_emptyArray = new(0); | |||
private static IEnumerator<T>? s_emptyEnumerator; | |||
|
|||
public static double SegmentGrowthRate { get; set; } = 2.0; |
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.
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast | ||
if ((uint)newCapacity > MaxLength) | ||
newCapacity = MaxLength; | ||
} | ||
|
||
// If the computed capacity is still less than specified, set to the original argument. | ||
// Capacities exceeding Array.MaxLength will be surfaced as OutOfMemoryException by Array.Resize. |
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.
💡 Need to update the branch following this to ensure the array is still a multiple of the segment size unless it's less than a single segment.
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.
It's not really needed though, right? Seems like we should just respect the size they requested if it's larger than we would be resizing to otherwise.
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.
AddRange
can grow by more than one, but we still want to retain page alignment. We only need to allow non-alignment for small collections, and collections where the user set Capacity
directly.
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.
Moved the code around, should be resolved
…mantics to indicate the shift amount, not the growth rate
Here's the numbers for shifts of 2 and 3 (1.25 and 1.125 growth rates respectively) with the test modified to specify the exact segment count such that the AddExtraItem takes it from a completely full segment group to the next outer segment allocation. The numbers are fairly close between the two shifts, with 1.25 performing better for full allocations and 1.125 performing better for "worst case" allocations, as expected. From my look over, 1.125 looks preferable, as it's looks like it does better when averaging out the best/worst cases for both wallclock time and allocations. |
…s properly size to execute in other cases.
By modifying this growth rate, we can reduce the amount of waste in a SegmentedList in scenarios where it's final capacity isn't known beforehand.
A growth rate of 2x matches the current code behavior. A growth rate of just over 1 matches the growth rate (1 segment) in the other PR (#75708).
All growth rates benchmarked: 1.000001, 1.1, 1.25, 1.5, 2
Obviously, the single segment growth rate is a non-starter without allowing null segments (which is the approach the other PR took).
The 2x rate matches current behavior, and is really only measured as a baseline. From my reading of this chart, it looks like 1.1 is the best of these choices.
*** Long benchmarking results ***