-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ADO.NET IHashPicker
customization API + Orleans v3-compatible IHashPicker
implementation
#9217
Changes from 1 commit
2eb7a2c
f0b0e57
ece6c5b
0a78193
cfd2670
5493a0c
d82b063
21ef966
03a33a2
b6f9b6f
d705b2c
9b6fc52
462e8cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
using System; | ||
using System.Buffers; | ||
using System.Text; | ||
|
||
namespace Orleans.Storage | ||
|
@@ -37,17 +38,63 @@ public int Hash(byte[] data) | |
// PickHasher parameters are the same for both calls so we need to analyze data content to distinguish these cases. | ||
// It doesn't word if string key is equal to grain type name, but we consider this edge case to be negligibly rare. | ||
|
||
// reducing allocations if data is not a grain type | ||
if (data.Length >= _grainType.Length && Encoding.UTF8.GetByteCount(_grainType) == data.Length) | ||
if (IsGrainTypeName(data)) | ||
return _innerHasher.Hash(data); | ||
|
||
var extendedLength = data.Length + 8; | ||
if (extendedLength <= 256) | ||
{ | ||
Span<byte> extended = stackalloc byte[extendedLength]; | ||
data.AsSpan().CopyTo(extended); | ||
return _innerHasher.Hash(extended); | ||
} | ||
|
||
var buffer = ArrayPool<byte>.Shared.Rent(extendedLength); | ||
try | ||
{ | ||
data.AsSpan().CopyTo(buffer); | ||
Array.Clear(buffer, data.Length, 8); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the I'd combine the two pathes, to avoid the duplicated logic (though it's very little logic here). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep, we need to clear rented buffer to make sure all these bytes set to zero - rented buffer can contain arbitrary data There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yes, I misread the code here. The extra 8 bytes need to be zeroed. As the span also needs to be cleared, these two code-pathes should be collapsed (see other comments). |
||
return _innerHasher.Hash(buffer.AsSpan(0, extendedLength)); | ||
} | ||
finally | ||
{ | ||
ArrayPool<byte>.Shared.Return(buffer); | ||
} | ||
} | ||
|
||
private bool IsGrainTypeName(byte[] data) | ||
{ | ||
// at least 1 byte per char | ||
if (data.Length < _grainType.Length) | ||
return false; | ||
|
||
var grainTypeByteCount = Encoding.UTF8.GetByteCount(_grainType); | ||
if (grainTypeByteCount != data.Length) | ||
return false; | ||
|
||
if (grainTypeByteCount <= 256) | ||
{ | ||
var grainTypeBytes = Encoding.UTF8.GetBytes(_grainType); | ||
if (grainTypeBytes.AsSpan().SequenceEqual(data)) | ||
return _innerHasher.Hash(data); | ||
Span<byte> grainTypeBytes = stackalloc byte[grainTypeByteCount]; | ||
if (!Encoding.UTF8.TryGetBytes(_grainType, grainTypeBytes, out _)) | ||
throw new InvalidOperationException(); | ||
|
||
return grainTypeBytes.SequenceEqual(data); | ||
} | ||
|
||
var extendedData = new byte[data.Length + 8]; | ||
data.CopyTo(extendedData, 0); | ||
return _innerHasher.Hash(extendedData); | ||
var buffer = ArrayPool<byte>.Shared.Rent(grainTypeByteCount); | ||
try | ||
{ | ||
var grainTypeBytes = buffer.AsSpan(0, grainTypeByteCount); | ||
|
||
if (!Encoding.UTF8.TryGetBytes(_grainType, grainTypeBytes, out _)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, combine the code paths. |
||
throw new InvalidOperationException(); | ||
|
||
return grainTypeBytes.SequenceEqual(data); | ||
} | ||
finally | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The pattern w/ |
||
{ | ||
ArrayPool<byte>.Shared.Return(buffer); | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stack-allocated should be to a constant of power of 2, then sliced. It's cheaper.
The extra space (extended) should also be cleared, just to be safe (see SkipLocalsInit).