-
Notifications
You must be signed in to change notification settings - Fork 545
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
GC Hole for SpanByte and other ones #38
Comments
This is a GC hole:
which is called by
which is a public API (found by @DaZombieKiller) |
None of these seem like real issues. We know |
This project seems to use Lines 27 to 28 in c16e1dd
arr[0] pointer to a new location and, as the result, this function may return something negative or huge (pretty much, random).
PS: the project seems to also use |
Got it, the
|
Note that in order to match and beat competing C++ caches, particularly for 99.9th percentile latencies, we had to do all the memory management ourselves when we could - which implied keeping pinned pages around for reuse over the lifetime of the server. |
This is correct. It was cumbersome/impossible to use byte* everywhere, particularly as C#'s type system prevented it being a generic parameter. Thankfully this is internal to the codebase, where we know exactly what we are doing. We are definitely open to other ways of handling this, that do not involve performance impact. |
This particular pain point can be worked around with a public readonly unsafe struct Pointer<T>
where T : unmanaged // not needed in C# 11
{
public readonly T* Value;
public Pointer(T* value) => Value = value;
public static implicit operator void*(Pointer<T> pointer) => pointer.Value;
public static implicit operator T*(Pointer<T> pointer) => pointer.Value;
// etc...
} The main thing to keep in mind with this is that it can't be used as a return type in interop code, because it being a struct means it may be passed differently in the ABI. I'd strongly suggest using a solution like this to handle generics instead of using Even if you're as careful as possible, there is no safeguard from the language, runtime or type system that ensures you don't accidentally This constructor is a good example: garnet/libs/storage/Tsavorite/cs/src/core/VarLen/UnmanagedMemoryManager.cs Lines 26 to 37 in c16e1dd
IMO it just shouldn't exist and callers should be required to use the pointer + length constructor, making it much less likely that they will accidentally pass in dangerous values. The convenience of just being able to pass a Span<T> in comes at a great safety cost that is only really mitigated by a small remark comment. Luckily, this constructor does not currently have any usages.
|
Thanks for the details. Yes, it should be possible to use wrapper structs throughout and avoid using Just wanted to mention that Garnet has been running for many months in production use cases without issues, so this is not an immediate concern for users. Since Garnet (and definitely none of these above-mentioned APIs) is not programmatically accessed, there isn't a danger of users misusing it, just we system developers and future contributors. Yet, it makes sense to avoid where possible without loss of performance. |
garnet/libs/storage/Tsavorite/cs/src/core/VarLen/SpanByte.cs
Line 61 in 1e5c7ad
this member is called here
garnet/libs/client/ClientSession/GarnetClientSessionMigrationExtensions.cs
Line 403 in 1e5c7ad
which this API is called from the public API
TryWriteKeyValueSpanByte
heregarnet/libs/client/ClientSession/GarnetClientSessionMigrationExtensions.cs
Line 296 in 1e5c7ad
which takes
ref SpanByte
.It is a GC hole since it's never pinned or otherwise fixed.
This is also a GC hole, since the memory is not fixed (you can also just use
Unsafe.SizeOf
here):garnet/libs/client/Utility.cs
Line 28 in 1e5c7ad
This is also seems to be a GC hole, since the memory is never fixed on this public API:
garnet/libs/storage/Tsavorite/cs/src/core/VarLen/SpanByteComparer.cs
Line 25 in 1e5c7ad
(note this list is not exhaustive)
The text was updated successfully, but these errors were encountered: