Skip to content
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

Avoid a list/array allocation in Task.WhenAll(enumerable) #110536

Merged
merged 1 commit into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ internal ref partial struct ValueListBuilder<T>
private T[]? _arrayFromPool;
private int _pos;

public ValueListBuilder(Span<T> initialSpan)
public ValueListBuilder(Span<T?> scratchBuffer)
{
_span = initialSpan;
_arrayFromPool = null;
_pos = 0;
_span = scratchBuffer!;
}

public ValueListBuilder(int capacity)
{
Grow(capacity);
}

public int Length
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5937,6 +5937,7 @@ public static Task WhenAll(IEnumerable<Task> tasks)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
}

int? count = null;
if (tasks is ICollection<Task> taskCollection)
{
if (tasks is Task[] taskArray)
Expand All @@ -5949,19 +5950,23 @@ public static Task WhenAll(IEnumerable<Task> tasks)
return WhenAll(CollectionsMarshal.AsSpan(taskList));
}

taskArray = new Task[taskCollection.Count];
taskCollection.CopyTo(taskArray, 0);
return WhenAll((ReadOnlySpan<Task>)taskArray);
count = taskCollection.Count;
}
else

// Buffer the tasks into a temporary span. Small sets of tasks are common,
// so for <= 8 we stack allocate.
ValueListBuilder<Task> builder = count is > 8 ?
new ValueListBuilder<Task>(count.Value) :
new ValueListBuilder<Task>([null, null, null, null, null, null, null, null]);
stephentoub marked this conversation as resolved.
Show resolved Hide resolved
foreach (Task task in tasks)
{
var taskList = new List<Task>();
foreach (Task task in tasks)
{
taskList.Add(task);
}
return WhenAll(CollectionsMarshal.AsSpan(taskList));
builder.Append(task);
}

Task t = WhenAll(builder.AsSpan());

builder.Dispose();
return t;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public RegexReplacement(string rep, RegexNode concat, Hashtable _caps)
[InlineArray(4)]
private struct FourStackStrings // used to do the equivalent of: Span<string> strings = stackalloc string[4];
{
private string _item1;
private string? _item1;
}

/// <summary>
Expand Down
Loading