mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-25 13:28:46 +00:00
perf: optimise subsequent GetHash and TryWriteHash calls
This commit is contained in:
parent
1157e36eff
commit
50d9cad2f3
@ -38,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
BigEndian/LittleEndian methods.
|
BigEndian/LittleEndian methods.
|
||||||
- X10D: `Stream.GetHash<>` and `Stream.TryWriteHash<>` now throw ArgumentException in lieu of
|
- X10D: `Stream.GetHash<>` and `Stream.TryWriteHash<>` now throw ArgumentException in lieu of
|
||||||
TypeInitializationException.
|
TypeInitializationException.
|
||||||
|
- X10D: `Stream.GetHash<>` and `Stream.TryWriteHash<>` are now more efficient on second and subsequent calls.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Reflection;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Reflection;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace X10D.IO;
|
namespace X10D.IO;
|
||||||
@ -8,6 +9,8 @@ namespace X10D.IO;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static partial class StreamExtensions
|
public static partial class StreamExtensions
|
||||||
{
|
{
|
||||||
|
private static readonly ConcurrentDictionary<Type, HashAlgorithm> HashAlgorithmCache = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the hash of the current stream as an array of bytes using the specified hash algorithm.
|
/// Returns the hash of the current stream as an array of bytes using the specified hash algorithm.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -37,6 +40,11 @@ public static partial class StreamExtensions
|
|||||||
throw new IOException(ExceptionMessages.StreamDoesNotSupportReading);
|
throw new IOException(ExceptionMessages.StreamDoesNotSupportReading);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HashAlgorithmCache.TryGetValue(typeof(T), out HashAlgorithm? cachedHashAlgorithm))
|
||||||
|
{
|
||||||
|
return cachedHashAlgorithm.ComputeHash(stream);
|
||||||
|
}
|
||||||
|
|
||||||
Type type = typeof(T);
|
Type type = typeof(T);
|
||||||
|
|
||||||
MethodInfo? createMethod = type.GetMethods(BindingFlags.Public | BindingFlags.Static)
|
MethodInfo? createMethod = type.GetMethods(BindingFlags.Public | BindingFlags.Static)
|
||||||
@ -52,6 +60,7 @@ public static partial class StreamExtensions
|
|||||||
throw new ArgumentException(ExceptionMessages.HashAlgorithmCreateReturnedNull);
|
throw new ArgumentException(ExceptionMessages.HashAlgorithmCreateReturnedNull);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HashAlgorithmCache.TryAdd(type, crypt);
|
||||||
return crypt.ComputeHash(stream);
|
return crypt.ComputeHash(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +100,13 @@ public static partial class StreamExtensions
|
|||||||
throw new IOException(ExceptionMessages.StreamDoesNotSupportReading);
|
throw new IOException(ExceptionMessages.StreamDoesNotSupportReading);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Span<byte> buffer = stackalloc byte[(int)stream.Length];
|
||||||
|
if (HashAlgorithmCache.TryGetValue(typeof(T), out HashAlgorithm? cachedHashAlgorithm))
|
||||||
|
{
|
||||||
|
_ = stream.Read(buffer); // we don't care about the number of bytes read. we can ignore MustUseReturnValue
|
||||||
|
return cachedHashAlgorithm.TryComputeHash(buffer, destination, out bytesWritten);
|
||||||
|
}
|
||||||
|
|
||||||
Type type = typeof(T);
|
Type type = typeof(T);
|
||||||
|
|
||||||
MethodInfo? createMethod = type.GetMethods(BindingFlags.Public | BindingFlags.Static)
|
MethodInfo? createMethod = type.GetMethods(BindingFlags.Public | BindingFlags.Static)
|
||||||
@ -111,7 +127,7 @@ public static partial class StreamExtensions
|
|||||||
throw new ArgumentException(ExceptionMessages.StreamTooLarge);
|
throw new ArgumentException(ExceptionMessages.StreamTooLarge);
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<byte> buffer = stackalloc byte[(int)stream.Length];
|
HashAlgorithmCache.TryAdd(type, crypt);
|
||||||
_ = stream.Read(buffer); // we don't care about the number of bytes read. we can ignore MustUseReturnValue
|
_ = stream.Read(buffer); // we don't care about the number of bytes read. we can ignore MustUseReturnValue
|
||||||
return crypt.TryComputeHash(buffer, destination, out bytesWritten);
|
return crypt.TryComputeHash(buffer, destination, out bytesWritten);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user