From 09be89ee4d2f90d047264a807267a7232aaf90ac Mon Sep 17 00:00:00 2001 From: Alexander Sher Date: Tue, 15 Nov 2022 01:33:43 -0600 Subject: [PATCH] Some perf improvements in Azure.Core and Azure.Storage --- .../src/Pipeline/HttpClientTransport.cs | 66 ++++++++++++++++++- .../Pipeline/HttpPipelineSynchronousPolicy.cs | 16 ++--- .../src/Azure.Storage.Common.csproj | 4 +- .../src/StorageSharedKeyCredential.cs | 10 ++- 4 files changed, 83 insertions(+), 13 deletions(-) diff --git a/sdk/core/Azure.Core/src/Pipeline/HttpClientTransport.cs b/sdk/core/Azure.Core/src/Pipeline/HttpClientTransport.cs index c65ada8fd261..2c3ab3cc88a1 100644 --- a/sdk/core/Azure.Core/src/Pipeline/HttpClientTransport.cs +++ b/sdk/core/Azure.Core/src/Pipeline/HttpClientTransport.cs @@ -207,25 +207,61 @@ private static HttpRequestMessage BuildRequestMessage(HttpMessage message) internal static bool TryGetHeader(HttpHeaders headers, HttpContent? content, string name, [NotNullWhen(true)] out string? value) { +#if NET6_0_OR_GREATER + if (headers.NonValidated.TryGetValues(name, out HeaderStringValues values) || + content is not null && content.Headers.NonValidated.TryGetValues(name, out values)) + { + value = JoinHeaderValues(values); + return true; + } +#else if (TryGetHeader(headers, content, name, out IEnumerable? values)) { value = JoinHeaderValues(values); return true; } - +#endif value = null; return false; } internal static bool TryGetHeader(HttpHeaders headers, HttpContent? content, string name, [NotNullWhen(true)] out IEnumerable? values) { +#if NET6_0_OR_GREATER + if (headers.NonValidated.TryGetValues(name, out HeaderStringValues headerStringValues) || + content != null && + content.Headers.NonValidated.TryGetValues(name, out headerStringValues)) + { + values = headerStringValues; + return true; + } + + values = null; + return false; +#else return headers.TryGetValues(name, out values) || content != null && content.Headers.TryGetValues(name, out values); +#endif + } internal static IEnumerable GetHeaders(HttpHeaders headers, HttpContent? content) { +#if NET6_0_OR_GREATER + foreach (var (key, value) in headers.NonValidated) + { + yield return new HttpHeader(key, JoinHeaderValues(value)); + } + + if (content is not null) + { + foreach (var (key, value) in content.Headers.NonValidated) + { + yield return new HttpHeader(key, JoinHeaderValues(value)); + } + } +#else foreach (KeyValuePair> header in headers) { yield return new HttpHeader(header.Key, JoinHeaderValues(header.Value)); @@ -238,28 +274,43 @@ internal static IEnumerable GetHeaders(HttpHeaders headers, HttpCont yield return new HttpHeader(header.Key, JoinHeaderValues(header.Value)); } } +#endif + } internal static bool RemoveHeader(HttpHeaders headers, HttpContent? content, string name) { // .Remove throws on invalid header name so use TryGet here to check +#if NET6_0_OR_GREATER + if (headers.NonValidated.Contains(name) && headers.Remove(name)) + { + return true; + } + + return content is not null && content.Headers.NonValidated.Contains(name) && content.Headers.Remove(name); +#else if (headers.TryGetValues(name, out _) && headers.Remove(name)) { return true; } return content?.Headers.TryGetValues(name, out _) == true && content.Headers.Remove(name); +#endif } internal static bool ContainsHeader(HttpHeaders headers, HttpContent? content, string name) { // .Contains throws on invalid header name so use TryGet here +#if NET6_0_OR_GREATER + return headers.NonValidated.Contains(name) || content is not null && content.Headers.NonValidated.Contains(name); +#else if (headers.TryGetValues(name, out _)) { return true; } return content?.Headers.TryGetValues(name, out _) == true; +#endif } internal static void CopyHeaders(HttpHeaders from, HttpHeaders to) @@ -272,11 +323,22 @@ internal static void CopyHeaders(HttpHeaders from, HttpHeaders to) } } } - +#if NET6_0_OR_GREATER + private static string JoinHeaderValues(HeaderStringValues values) + { + return values.Count switch + { + 0 => string.Empty, + 1 => values.ToString(), + _ => string.Join(",", values) + }; + } +#else private static string JoinHeaderValues(IEnumerable values) { return string.Join(",", values); } +#endif private sealed class PipelineRequest : Request { diff --git a/sdk/core/Azure.Core/src/Pipeline/HttpPipelineSynchronousPolicy.cs b/sdk/core/Azure.Core/src/Pipeline/HttpPipelineSynchronousPolicy.cs index 6c9c958be733..e24d9fd75c08 100644 --- a/sdk/core/Azure.Core/src/Pipeline/HttpPipelineSynchronousPolicy.cs +++ b/sdk/core/Azure.Core/src/Pipeline/HttpPipelineSynchronousPolicy.cs @@ -40,13 +40,6 @@ public override void Process(HttpMessage message, ReadOnlyMemory public override ValueTask ProcessAsync(HttpMessage message, ReadOnlyMemory pipeline) { - async ValueTask ProcessAsyncInner(HttpMessage message, ReadOnlyMemory pipeline) - { - OnSendingRequest(message); - await ProcessNextAsync(message, pipeline).ConfigureAwait(false); - OnReceivedResponse(message); - } - if (!_hasOnReceivedResponse) { // If OnReceivedResponse was not overridden we can avoid creating a state machine and return the task directly @@ -54,7 +47,14 @@ async ValueTask ProcessAsyncInner(HttpMessage message, ReadOnlyMemory pipeline) + { + OnSendingRequest(message); + await ProcessNextAsync(message, pipeline).ConfigureAwait(false); + OnReceivedResponse(message); } /// diff --git a/sdk/storage/Azure.Storage.Common/src/Azure.Storage.Common.csproj b/sdk/storage/Azure.Storage.Common/src/Azure.Storage.Common.csproj index e3053b1a01bd..0918ce2b12ea 100644 --- a/sdk/storage/Azure.Storage.Common/src/Azure.Storage.Common.csproj +++ b/sdk/storage/Azure.Storage.Common/src/Azure.Storage.Common.csproj @@ -1,6 +1,8 @@ - $(RequiredTargetFrameworks) + $(RequiredTargetFrameworks);net6.0 + + false Microsoft Azure.Storage.Common client library diff --git a/sdk/storage/Azure.Storage.Common/src/StorageSharedKeyCredential.cs b/sdk/storage/Azure.Storage.Common/src/StorageSharedKeyCredential.cs index 54fda26948c1..5d79498d5001 100644 --- a/sdk/storage/Azure.Storage.Common/src/StorageSharedKeyCredential.cs +++ b/sdk/storage/Azure.Storage.Common/src/StorageSharedKeyCredential.cs @@ -65,8 +65,14 @@ public void SetAccountKey(string accountKey) => /// /// The message to sign. /// The signed message. - internal string ComputeHMACSHA256(string message) => - Convert.ToBase64String(new HMACSHA256(AccountKeyValue).ComputeHash(Encoding.UTF8.GetBytes(message))); + internal string ComputeHMACSHA256(string message) + { +#if NET6_0_OR_GREATER + return Convert.ToBase64String(HMACSHA256.HashData(AccountKeyValue, Encoding.UTF8.GetBytes(message))); +#else + return Convert.ToBase64String(new HMACSHA256(AccountKeyValue).ComputeHash(Encoding.UTF8.GetBytes(message))); +#endif + } /// /// Generates a base-64 hash signature string for an HTTP request or