-
Notifications
You must be signed in to change notification settings - Fork 623
LogRecord and SpanByte changes #1186
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
base: dev
Are you sure you want to change the base?
Conversation
- Move CountdownWrapper to its own file - Rename Lockable* to Transactional* - Rename Transient* to Ephemeral*
Other work to get CreateNewRecordRMW clean
…ns first pass done)
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.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
| var storeWrapper = clusterProvider.storeWrapper; | ||
| var transientObjectIdMap = storeWrapper.store.Log.TransientObjectIdMap; | ||
|
|
||
| // Use try/finally instead of "using" because we don't want the boxing that an interface call would entail. Double-Dispose() is OK for DiskLogRecord. |
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.
using does not box its argument, it'll do a constrained virtual call on a value type.
S() will compile to something like:
IL_0000 ldloca.s 00
IL_0002 initobj FooStruct
IL_0008 leave.s IL_0018
IL_000A ldloca.s 00
IL_000C constrained. FooStruct
IL_0012 callvirt IDisposable.Dispose ()
IL_0017 endfinally
IL_0018 ret
O() to:
IL_0000 newobj FooObj..ctor
IL_0005 stloc.0
IL_0006 leave.s IL_0012
IL_0008 ldloc.0
IL_0009 brfalse.s IL_0011
IL_000B ldloc.0
IL_000C callvirt IDisposable.Dispose ()
IL_0011 endfinally
IL_0012 ret
Note the absence of any box ops in S() - the only real difference is the constrained prefix.
libs/server/Storage/Session/Common/ArrayKeyIterationFunctions.cs
Outdated
Show resolved
Hide resolved
libs/storage/Tsavorite/cs/src/core/Allocator/ObjectAllocatorImpl.cs
Outdated
Show resolved
Hide resolved
| internal readonly bool IsSet => SegmentSizeBits != 0; | ||
| internal readonly bool HasData => word != 0 && word != NotSet; | ||
|
|
||
| public ObjectLogFilePositionInfo() |
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.
Empty struct constructors are tricky - they aren't invoked for default, or when a struct is implicitly initialized (like when it's a field). That is, new ObjectLogFilePositionInfo().word != default(ObjectLogFilePositionInfo).word.
Makes me a bit nervous.
| firstRead = true; | ||
| } | ||
|
|
||
| // Note: We may be sending to multiple replicas, so cannot serialize LogRecords directly to the network 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.
Every connection has a distinct network buffer, so we can technically serialize it directly to the network buffer.
Is there another reason why we cannot write the key,value pair directly to the network buffer as previously?
| /// </summary> | ||
| public PinnedSpanByte GetAvailableNetworkBufferSpan() => PinnedSpanByte.FromPinnedPointer(curr, (int)(end - curr)); | ||
|
|
||
| public void IncrementRecordDirect(int size) |
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.
Looks like this is not used anywhere? Do we need it?
| db.MainStore.Reset(); | ||
| if (db.ObjectStore?.Log.TailAddress > 64) | ||
| db.ObjectStore?.Reset(); | ||
| if (db.Store.Log.TailAddress > 64) |
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.
Should this be PageHeader.Size?
libs/server/Storage/Session/Common/ArrayKeyIterationFunctions.cs
Outdated
Show resolved
Hide resolved
| var valueSB = scratchBufferBuilder.FormatScratch(sizeof(long), value).SpanByte; | ||
| valueSB.ExtraMetadata = DateTimeOffset.UtcNow.Ticks + expiry.Ticks; | ||
| return SET(ref _key, ref valueSB, ref context); | ||
| var input = new RawStringInput(RespCommand.APPEND, ref parseState, arg1: DateTimeOffset.UtcNow.Ticks + expiry.Ticks); |
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.
Why APPEND?
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.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
…threshold configuration option
…object-log segments); PendingContext is no longer itself a TSourceLogRecord;

This PR converts Garnet to use a new ObjectAllocator with a revised in-memory and on-disk format that will use only a single log file, change ISessionFunctions to be (Disk)LogRecord-based and propagate this to operations such as Compaction and Migration, remove TKey and TValue from TsavoriteKV, and many related refactors.
Highlights:
(ReadOnly)Span<byte>extensions.ReadOnlySpan<byte>at the StorageSession and below, including Tsavorite. There are no longer any byte[] keys. The TKey type argument is gone from Tsavorite and Garnet.(ReadOnly)Span<byte>or objects implementing IHeapObject. TValue has been removed from TsavoriteKV.Major remaining tasks to be addressed in follow-on PRs:
(ReadOnly)Span<byte>path by replacing byte* usage (such as was done for Utility.HashBytes).