Skip to content

Commit

Permalink
Reduce allocations caused by Range operators on arrays and strings (d…
Browse files Browse the repository at this point in the history
…otnet#46519)

* Reduce allocations caused by Range operators on arrays and strings

Using the Range operator on an array or string causes a new array or string allocation, which may not be necessary. In these cases, we don't need to allocate an intermediate array or string, and can just use a span instead.

Fixed minor spelling mistakes in adjacent code.
  • Loading branch information
eerhardt authored Feb 9, 2023
1 parent f58f954 commit a4bbcba
Show file tree
Hide file tree
Showing 6 changed files with 17 additions and 9 deletions.
4 changes: 2 additions & 2 deletions src/Http/Http/src/Internal/ResponseCookies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public void Append(ReadOnlySpan<KeyValuePair<string, string>> keyValuePairs, Coo
}
}

var cookieSuffix = options.CreateCookieHeader(string.Empty, string.Empty).ToString()[1..];
var cookieSuffix = options.CreateCookieHeader(string.Empty, string.Empty).ToString().AsSpan(1);
var cookies = new string[keyValuePairs.Length];
var position = 0;

Expand All @@ -98,7 +98,7 @@ public void Append(ReadOnlySpan<KeyValuePair<string, string>> keyValuePairs, Coo
}

// Can't use += as StringValues does not override operator+
// and the implict conversions will cause an incorrect string concat https://github.com/dotnet/runtime/issues/52507
// and the implicit conversions will cause an incorrect string concat https://github.com/dotnet/runtime/issues/52507
Headers.SetCookie = StringValues.Concat(Headers.SetCookie, cookies);
}

Expand Down
6 changes: 3 additions & 3 deletions src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,7 @@ private async Task ProcessHeadersFrameAsync<TContext>(IHttpApplication<TContext>
if (string.Equals(HttpRequestHeaders.HeaderProtocol, WebTransportSession.WebTransportProtocolValue, StringComparison.Ordinal))
{
// if the client supports the same version of WebTransport as Kestrel, make this a WebTransport request
if (((AspNetCore.Http.IHeaderDictionary)HttpRequestHeaders).TryGetValue(WebTransportSession.CurrentSuppportedVersion, out var version) && string.Equals(version, WebTransportSession.VersionEnabledIndicator, StringComparison.Ordinal))
if (((AspNetCore.Http.IHeaderDictionary)HttpRequestHeaders).TryGetValue(WebTransportSession.CurrentSupportedVersion, out var version) && string.Equals(version, WebTransportSession.VersionEnabledIndicator, StringComparison.Ordinal))
{
IsWebTransportRequest = true;
}
Expand Down Expand Up @@ -1201,13 +1201,13 @@ public override async ValueTask<IWebTransportSession> AcceptAsync(CancellationTo

if (!IsWebTransportRequest)
{
throw new InvalidOperationException(CoreStrings.FormatFailedToNegotiateCommonWebTransportVersion(WebTransportSession.CurrentSuppportedVersion));
throw new InvalidOperationException(CoreStrings.FormatFailedToNegotiateCommonWebTransportVersion(WebTransportSession.CurrentSupportedVersion));
}

_isWebTransportSessionAccepted = true;

// version negotiation
var version = WebTransportSession.CurrentSuppportedVersion[WebTransportSession.SecPrefix.Length..];
var version = WebTransportSession.CurrentSupportedVersionSuffix;

_context.WebTransportSession = _context.Connection!.OpenNewWebTransportSession(this);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ internal sealed class WebTransportSession : IWebTransportSession
internal const string VersionEnabledIndicator = "1";
internal const string SecPrefix = "sec-webtransport-http3-";
internal const string VersionHeaderPrefix = $"{SecPrefix}draft";
internal const string CurrentSuppportedVersion = $"{VersionHeaderPrefix}02";
internal const string CurrentSupportedVersionSuffix = "draft02";
internal const string CurrentSupportedVersion = $"{SecPrefix}{CurrentSupportedVersionSuffix}";

public long SessionId => _connectStream.StreamId;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ await Http3Api.InitializeConnectionAsync(async context =>
new KeyValuePair<string, string>(InternalHeaderNames.Path, "/"),
new KeyValuePair<string, string>(InternalHeaderNames.Authority, "server.example.com"),
new KeyValuePair<string, string>(HeaderNames.Origin, "server.example.com"),
new KeyValuePair<string, string>(WebTransportSession.CurrentSuppportedVersion, "1")
new KeyValuePair<string, string>(WebTransportSession.CurrentSupportedVersion, "1")
});

var response2 = await requestStream.ExpectHeadersAsync();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ await inMemory.InitializeConnectionAsync(async context =>
new KeyValuePair<string, string>(InternalHeaderNames.Path, "/"),
new KeyValuePair<string, string>(InternalHeaderNames.Authority, "server.example.com"),
new KeyValuePair<string, string>(HeaderNames.Origin, "server.example.com"),
new KeyValuePair<string, string>(WebTransportSession.CurrentSuppportedVersion, "1")
new KeyValuePair<string, string>(WebTransportSession.CurrentSupportedVersion, "1")
});

return (WebTransportSession)await appCompletedTcs.Task;
Expand Down
9 changes: 8 additions & 1 deletion src/Shared/PropertyAsParameterInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,14 @@ public static ReadOnlySpan<ParameterInfo> Flatten(ParameterInfo[] parameters, Pa
{
// Initialize the list with all parameter already processed
// to keep the same parameter ordering
flattenedParameters ??= new(parameters[0..i]);
static List<ParameterInfo> InitializeList(ParameterInfo[] parameters, int i)
{
// will add the rest of the parameters to this list, so set initial capacity to reduce growing the list
List<ParameterInfo> list = new(parameters.Length);
list.AddRange(parameters.AsSpan(0, i));
return list;
}
flattenedParameters ??= InitializeList(parameters, i);
nullabilityContext ??= new();

var isNullable = Nullable.GetUnderlyingType(parameters[i].ParameterType) != null ||
Expand Down

0 comments on commit a4bbcba

Please sign in to comment.