Skip to content

Commit fdfe440

Browse files
committed
Optimized string concatenation with string.Create
Replaced `StringBuilder` concatenation with the more efficient `string.Create` method for creating new strings by concatenating `scheme`, `host`, `pathBase`, `path`, and `queryString`. This method reduces overhead by avoiding multiple string concatenations and allocating the correct buffer size for the new string. The `CopyTo` method is used in a callback function to copy each string to the new string, slicing the buffer to remove the copied part. The `SchemeDelimiter` is always copied to the new string, regardless of its length. This change enhances the performance of the code.
1 parent 5ff2399 commit fdfe440

File tree

1 file changed

+39
-10
lines changed

1 file changed

+39
-10
lines changed

src/Http/Http.Extensions/src/UriHelper.cs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Buffers;
55
using System.Diagnostics.CodeAnalysis;
66
using System.Runtime.CompilerServices;
7-
using System.Text;
87

98
namespace Microsoft.AspNetCore.Http.Extensions;
109

@@ -210,18 +209,48 @@ public static string GetDisplayUrl(this HttpRequest request)
210209
var path = request.Path.Value ?? string.Empty;
211210
var queryString = request.QueryString.Value ?? string.Empty;
212211

213-
// PERF: Calculate string length to allocate correct buffer size for StringBuilder.
214212
var length = scheme.Length + SchemeDelimiter.Length + host.Length
215213
+ pathBase.Length + path.Length + queryString.Length;
216214

217-
return new StringBuilder(length)
218-
.Append(scheme)
219-
.Append(SchemeDelimiter)
220-
.Append(host)
221-
.Append(pathBase)
222-
.Append(path)
223-
.Append(queryString)
224-
.ToString();
215+
return string.Create(
216+
length,
217+
(scheme, host, pathBase, path, queryString),
218+
static (buffer, uriParts) =>
219+
{
220+
var (scheme, host, pathBase, path, queryString) = uriParts;
221+
222+
if (scheme.Length > 0)
223+
{
224+
scheme.CopyTo(buffer);
225+
buffer = buffer.Slice(scheme.Length);
226+
}
227+
228+
SchemeDelimiter.CopyTo(buffer);
229+
buffer = buffer.Slice(SchemeDelimiter.Length);
230+
231+
if (host.Length > 0)
232+
{
233+
host.CopyTo(buffer);
234+
buffer = buffer.Slice(host.Length);
235+
}
236+
237+
if (pathBase.Length > 0)
238+
{
239+
pathBase.CopyTo(buffer);
240+
buffer = buffer.Slice(pathBase.Length);
241+
}
242+
243+
if (path.Length > 0)
244+
{
245+
path.CopyTo(buffer);
246+
buffer = buffer.Slice(path.Length);
247+
}
248+
249+
if (queryString.Length > 0)
250+
{
251+
queryString.CopyTo(buffer);
252+
}
253+
});
225254
}
226255

227256
/// <summary>

0 commit comments

Comments
 (0)