I'm trying to figure out which one of these classes below is faster, so I decided to write a BenchmarkDotNet test.
public class RequestSignerBenchmark { [Benchmark] public void First() { var signer = RequestSigner2.FromSecret("hidden"); var timestamp = TimestampProvider.Default.CurrentTimestamp(); signer.Sign(timestamp, "GET", "products", ""); } [Benchmark] public void Second() { var signer = RequestSigner.FromSecret("hidden"); var timestamp = TimestampProvider.Default.CurrentTimestamp(); signer.Sign(timestamp, "GET", "products", ""); } } // Program.cs BenchmarkRunner.Run<RequestSignerBenchmark>(); I'm not sure that I'm running that the test I made is correct. Isn't the First() supposed to be faster judging by the code? If it's wrong, what would an appropriate test would look like?
| Method | Mean | Error | StdDev | |------- |---------:|----------:|----------:| | First | 3.234 us | 0.0646 us | 0.1769 us | | Second | 2.659 us | 0.0516 us | 0.0614 us | Classes to evaluate
public sealed class RequestSigner { private readonly byte[] _base64Secret; public RequestSigner(byte[] base64Secret) { _base64Secret = base64Secret; } public static RequestSigner FromSecret(string secret) { return new RequestSigner(Convert.FromBase64String(secret)); } public string Sign(string timestamp, string method, string requestPath, string body) { var orig = Encoding.UTF8.GetBytes(timestamp + method.ToUpperInvariant() + requestPath + body); using var hmac = new HMACSHA256(_base64Secret); return Convert.ToBase64String(hmac.ComputeHash(orig)); } } public class RequestSigner2 : IDisposable { private readonly HMACSHA256 _hmac; public RequestSigner2(byte[] base64Secret) { _hmac = new HMACSHA256(base64Secret); } public static RequestSigner2 FromSecret(string secret) { return new RequestSigner2(Convert.FromBase64String(secret)); } public string Sign(string timestamp, string method, string requestPath, string body) { DoDisposeChecks(); if (string.IsNullOrWhiteSpace(method) || string.IsNullOrWhiteSpace(requestPath)) { return string.Empty; } var orig = Encoding.UTF8.GetBytes(timestamp + method.ToUpperInvariant() + requestPath + body); return Convert.ToBase64String(_hmac.ComputeHash(orig)); } #region Disposable private bool _isDisposed; /// <summary> /// Checks if this object has been disposed. /// </summary> /// <exception cref="ObjectDisposedException">Thrown if the object has been disposed.</exception> [MethodImpl(MethodImplOptions.AggressiveInlining)] protected void DoDisposeChecks() { if (_isDisposed) { throw new ObjectDisposedException(nameof(RequestSigner2)); } } /// <inheritdoc /> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// Disposes of managed and unmanaged resources. /// </summary> /// <param name="disposing">A value indicating whether or not to dispose of managed resources.</param> protected virtual void Dispose(bool disposing) { if (_isDisposed) { return; } if (disposing) { _hmac.Dispose(); } _isDisposed = true; } #endregion } 

RequestSigner2) should be faster?