Skip to content

Commit a4bbcba

Browse files
authored
Reduce allocations caused by Range operators on arrays and strings (#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.
1 parent f58f954 commit a4bbcba

File tree

6 files changed

+17
-9
lines changed

6 files changed

+17
-9
lines changed

src/Http/Http/src/Internal/ResponseCookies.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public void Append(ReadOnlySpan<KeyValuePair<string, string>> keyValuePairs, Coo
8787
}
8888
}
8989

90-
var cookieSuffix = options.CreateCookieHeader(string.Empty, string.Empty).ToString()[1..];
90+
var cookieSuffix = options.CreateCookieHeader(string.Empty, string.Empty).ToString().AsSpan(1);
9191
var cookies = new string[keyValuePairs.Length];
9292
var position = 0;
9393

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

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

src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ private async Task ProcessHeadersFrameAsync<TContext>(IHttpApplication<TContext>
841841
if (string.Equals(HttpRequestHeaders.HeaderProtocol, WebTransportSession.WebTransportProtocolValue, StringComparison.Ordinal))
842842
{
843843
// if the client supports the same version of WebTransport as Kestrel, make this a WebTransport request
844-
if (((AspNetCore.Http.IHeaderDictionary)HttpRequestHeaders).TryGetValue(WebTransportSession.CurrentSuppportedVersion, out var version) && string.Equals(version, WebTransportSession.VersionEnabledIndicator, StringComparison.Ordinal))
844+
if (((AspNetCore.Http.IHeaderDictionary)HttpRequestHeaders).TryGetValue(WebTransportSession.CurrentSupportedVersion, out var version) && string.Equals(version, WebTransportSession.VersionEnabledIndicator, StringComparison.Ordinal))
845845
{
846846
IsWebTransportRequest = true;
847847
}
@@ -1201,13 +1201,13 @@ public override async ValueTask<IWebTransportSession> AcceptAsync(CancellationTo
12011201

12021202
if (!IsWebTransportRequest)
12031203
{
1204-
throw new InvalidOperationException(CoreStrings.FormatFailedToNegotiateCommonWebTransportVersion(WebTransportSession.CurrentSuppportedVersion));
1204+
throw new InvalidOperationException(CoreStrings.FormatFailedToNegotiateCommonWebTransportVersion(WebTransportSession.CurrentSupportedVersion));
12051205
}
12061206

12071207
_isWebTransportSessionAccepted = true;
12081208

12091209
// version negotiation
1210-
var version = WebTransportSession.CurrentSuppportedVersion[WebTransportSession.SecPrefix.Length..];
1210+
var version = WebTransportSession.CurrentSupportedVersionSuffix;
12111211

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

src/Servers/Kestrel/Core/src/Internal/WebTransport/WebTransportSession.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ internal sealed class WebTransportSession : IWebTransportSession
3838
internal const string VersionEnabledIndicator = "1";
3939
internal const string SecPrefix = "sec-webtransport-http3-";
4040
internal const string VersionHeaderPrefix = $"{SecPrefix}draft";
41-
internal const string CurrentSuppportedVersion = $"{VersionHeaderPrefix}02";
41+
internal const string CurrentSupportedVersionSuffix = "draft02";
42+
internal const string CurrentSupportedVersion = $"{SecPrefix}{CurrentSupportedVersionSuffix}";
4243

4344
public long SessionId => _connectStream.StreamId;
4445

src/Servers/Kestrel/test/InMemory.FunctionalTests/Http3/WebTransport/WebTransportHandshakeTests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ await Http3Api.InitializeConnectionAsync(async context =>
7171
new KeyValuePair<string, string>(InternalHeaderNames.Path, "/"),
7272
new KeyValuePair<string, string>(InternalHeaderNames.Authority, "server.example.com"),
7373
new KeyValuePair<string, string>(HeaderNames.Origin, "server.example.com"),
74-
new KeyValuePair<string, string>(WebTransportSession.CurrentSuppportedVersion, "1")
74+
new KeyValuePair<string, string>(WebTransportSession.CurrentSupportedVersion, "1")
7575
});
7676

7777
var response2 = await requestStream.ExpectHeadersAsync();

src/Servers/Kestrel/test/InMemory.FunctionalTests/Http3/WebTransport/WebTransportTestUtilities.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ await inMemory.InitializeConnectionAsync(async context =>
6565
new KeyValuePair<string, string>(InternalHeaderNames.Path, "/"),
6666
new KeyValuePair<string, string>(InternalHeaderNames.Authority, "server.example.com"),
6767
new KeyValuePair<string, string>(HeaderNames.Origin, "server.example.com"),
68-
new KeyValuePair<string, string>(WebTransportSession.CurrentSuppportedVersion, "1")
68+
new KeyValuePair<string, string>(WebTransportSession.CurrentSupportedVersion, "1")
6969
});
7070

7171
return (WebTransportSession)await appCompletedTcs.Task;

src/Shared/PropertyAsParameterInfo.cs

+8-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,14 @@ public static ReadOnlySpan<ParameterInfo> Flatten(ParameterInfo[] parameters, Pa
8585
{
8686
// Initialize the list with all parameter already processed
8787
// to keep the same parameter ordering
88-
flattenedParameters ??= new(parameters[0..i]);
88+
static List<ParameterInfo> InitializeList(ParameterInfo[] parameters, int i)
89+
{
90+
// will add the rest of the parameters to this list, so set initial capacity to reduce growing the list
91+
List<ParameterInfo> list = new(parameters.Length);
92+
list.AddRange(parameters.AsSpan(0, i));
93+
return list;
94+
}
95+
flattenedParameters ??= InitializeList(parameters, i);
8996
nullabilityContext ??= new();
9097

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

0 commit comments

Comments
 (0)