diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/AsymmetricAdapterSignatures.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/AsymmetricAdapterSignatures.cs new file mode 100644 index 0000000000..badfc06600 --- /dev/null +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/AsymmetricAdapterSignatures.cs @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#if NET6_0_OR_GREATER + +using System; +using System.Buffers; +using System.Security.Cryptography; +using System.Text; +using BenchmarkDotNet.Attributes; +using Microsoft.IdentityModel.JsonWebTokens; +using Microsoft.IdentityModel.Tokens; + +namespace Microsoft.IdentityModel.Benchmarks +{ + // dotnet run -c release -f net8.0 --filter Microsoft.IdentityModel.Benchmarks.AsymmetricAdapterSignatures.* + + [Config(typeof(BenchmarkConfig))] + [HideColumns("Type", "Job", "WarmupCount", "LaunchCount")] + [MemoryDiagnoser] + public class AsymmetricAdapterSignatures + { + private byte[] _bytesToSign; + private byte[] _signatureBuffer; + private AsymmetricAdapter _rsaAsymmetricAdapter; + + [GlobalSetup] + public void Setup() + { + SecurityTokenDescriptor securityTokenDescriptor = new () + { + SigningCredentials = BenchmarkUtils.SigningCredentialsRsaSha256, + Claims = BenchmarkUtils.Claims, + TokenType = JwtHeaderParameterNames.Jwk + }; + + _bytesToSign = Encoding.UTF8.GetBytes((new JsonWebTokenHandler()).CreateToken(securityTokenDescriptor)); + _rsaAsymmetricAdapter = new AsymmetricAdapter( + BenchmarkUtils.SigningCredentialsRsaSha256.Key, + SecurityAlgorithms.RsaSha256, + SHA256.Create(), + SupportedAlgorithms.GetHashAlgorithmName(SecurityAlgorithms.RsaSha256), + true ); + + _signatureBuffer = new byte[256]; + } + + /// + /// In this case, dotnet creates a buffer to hold the signature. + /// ArrayPool is not used, because the buffer is created by the framework and not the user. + /// The buffer is not returned to the pool, and must be garbage collected. + /// + [Benchmark] + public void SignDotnetCreatingBufferRSA() + { + _rsaAsymmetricAdapter.Sign(_bytesToSign); + } + + /// + /// In this case, the user obatins a buffer to hold the signature frm the array pool. + /// A new api available in .NET 5.0+ is used to provide the buffer to place the signature. + /// The size of the bytes written is returned in the out parameter, size. + /// + [Benchmark] + public void SignSpanWithArrayPoolRSA() + { + byte[] signature = ArrayPool.Shared.Rent(256); + _rsaAsymmetricAdapter.SignUsingSpan(_bytesToSign, signature.AsSpan(), out int size); + ArrayPool.Shared.Return(signature); + } + + /// + /// In this case, the user has created a SINGLE global buffer to hold the signature. + /// This is not a recommended approach, because the buffer will be reused and signatures will get mixed up. + /// Is used to illustrate that using the array pool is cheap. + /// Uses a new api available in .NET 5.0 + to provide the buffer to place the signature. + /// The size of the bytes written is returned in the out parameter, size. + /// + [Benchmark] + public void SignSpanWithFixedBufferRSA() + { + _rsaAsymmetricAdapter.SignUsingSpan(_bytesToSign, _signatureBuffer, out int size); + } + } +} +#endif diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/BenchmarkConfig.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/BenchmarkConfig.cs index f89730e3b7..0393edfc36 100644 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/BenchmarkConfig.cs +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/BenchmarkConfig.cs @@ -5,6 +5,7 @@ using BenchmarkDotNet.Configs; using BenchmarkDotNet.Jobs; using BenchmarkDotNet.Toolchains.InProcess.Emit; +using Perfolizer.Horology; namespace Microsoft.IdentityModel.Benchmarks { @@ -13,8 +14,12 @@ public class BenchmarkConfig : ManualConfig public BenchmarkConfig() { AddJob(Job.MediumRun - .WithToolchain(InProcessEmitToolchain.Instance)) - .AddColumn(StatisticColumn.P90, StatisticColumn.P95, StatisticColumn.P100); + .WithToolchain(InProcessEmitToolchain.Instance) + .WithLaunchCount(4) + .WithMaxAbsoluteError(TimeInterval.FromMilliseconds(10))) + // uncomment to disable validation to enable debuging through benchmarks + //.WithOption(ConfigOptions.DisableOptimizationsValidator, true) + .AddColumn(StatisticColumn.P90, StatisticColumn.P95, StatisticColumn.P100); } } } diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/Program.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/Program.cs index a79c3fac55..235542e2c5 100644 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/Program.cs +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/Program.cs @@ -1,12 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -//#define DEBUG_TESTS - -#if DEBUG_TESTS using Microsoft.IdentityModel.Protocols.SignedHttpRequest; using Microsoft.IdentityModel.Tokens; -#endif using BenchmarkDotNet.Running; namespace Microsoft.IdentityModel.Benchmarks @@ -15,15 +11,18 @@ public static class Program { public static void Main(string[] args) { -#if DEBUG_TESTS - DebugThroughTests(); -#endif + //DebugThroughTests(); + BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args); } - -#if DEBUG_TESTS private static void DebugThroughTests() { + AsymmetricAdapterSignatures asymmetricAdapter = new AsymmetricAdapterSignatures(); + asymmetricAdapter.Setup(); + asymmetricAdapter.SignDotnetCreatingBufferRSA(); + asymmetricAdapter.SignSpanWithArrayPoolRSA(); + asymmetricAdapter.SignSpanWithFixedBufferRSA(); + CreateJWETests createJWETests = new CreateJWETests(); createJWETests.Setup(); string jwe = createJWETests.JsonWebTokenHandler_CreateJWE(); @@ -44,6 +43,5 @@ private static void DebugThroughTests() validateSignedHttpRequestAsyncTests.Setup(); SignedHttpRequestValidationResult signedHttpRequestValidationResult = validateSignedHttpRequestAsyncTests.SHRHandler_ValidateSignedHttpRequestAsync().Result; } -#endif } } diff --git a/src/Microsoft.IdentityModel.Tokens/Properties/AssemblyInfo.cs b/src/Microsoft.IdentityModel.Tokens/Properties/AssemblyInfo.cs index 65c4dee54d..f27198cc90 100644 --- a/src/Microsoft.IdentityModel.Tokens/Properties/AssemblyInfo.cs +++ b/src/Microsoft.IdentityModel.Tokens/Properties/AssemblyInfo.cs @@ -13,11 +13,11 @@ [assembly: CLSCompliant(true)] [assembly: ComVisible(false)] -[assembly: InternalsVisibleTo("Microsoft.IdentityModel.Tokens.Saml, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("System.IdentityModel.Tokens.Jwt, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +[assembly: InternalsVisibleTo("Microsoft.IdentityModel.Benchmarks, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("Microsoft.IdentityModel.JsonWebTokens, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("Microsoft.IdentityModel.Protocols.SignedHttpRequest, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("Microsoft.IdentityModel.Protocols.SignedHttpRequest.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +[assembly: InternalsVisibleTo("Microsoft.IdentityModel.Tokens.Saml, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("Microsoft.IdentityModel.Xml, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("Microsoft.AzureAD.SmartSessionEvaluator, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("Microsoft.IdentityModel.KeyVaultExtensions.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] @@ -33,3 +33,4 @@ [assembly: InternalsVisibleTo("Microsoft.IdentityModel.S2S.Extensions.AspNetCore.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tokens, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tokens.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +[assembly: InternalsVisibleTo("System.IdentityModel.Tokens.Jwt, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]