diff --git a/libs/client/Utility.cs b/libs/client/Utility.cs index d9c2237a32..37c8953fd1 100644 --- a/libs/client/Utility.cs +++ b/libs/client/Utility.cs @@ -16,18 +16,6 @@ namespace Garnet.client /// public static class Utility { - /// - /// Get size of type - /// - /// - /// - /// - internal static unsafe int GetSize(this T value) - { - T[] arr = new T[2]; - return (int)((long)Unsafe.AsPointer(ref arr[1]) - (long)Unsafe.AsPointer(ref arr[0])); - } - /// /// Parse size in string notation into long. /// Examples: 4k, 4K, 4KB, 4 KB, 8m, 8MB, 12g, 12 GB, 16t, 16 TB, 32p, 32 PB. diff --git a/libs/storage/Tsavorite/cs/src/core/Allocator/BlittableAllocator.cs b/libs/storage/Tsavorite/cs/src/core/Allocator/BlittableAllocator.cs index 3b520518c2..7af683fa42 100644 --- a/libs/storage/Tsavorite/cs/src/core/Allocator/BlittableAllocator.cs +++ b/libs/storage/Tsavorite/cs/src/core/Allocator/BlittableAllocator.cs @@ -16,13 +16,9 @@ internal sealed unsafe class BlittableAllocator : AllocatorBase)); - private static readonly int recordInfoSize = Utility.GetSize(default(RecordInfo)); - private static readonly int keySize = Utility.GetSize(default(Key)); - private static readonly int valueSize = Utility.GetSize(default(Value)); - - internal static int RecordSize => recordSize; + internal static int KeySize => Unsafe.SizeOf(); + internal static int ValueSize => Unsafe.SizeOf(); + internal static int RecordSize => Unsafe.SizeOf>(); private readonly OverflowPool overflowPagePool; @@ -88,37 +84,34 @@ public override ref Key GetKey(long physicalAddress) public override ref Value GetValue(long physicalAddress) { - return ref Unsafe.AsRef((byte*)physicalAddress + RecordInfo.GetLength() + keySize); + return ref Unsafe.AsRef((byte*)physicalAddress + RecordInfo.GetLength() + KeySize); } public override (int actualSize, int allocatedSize) GetRecordSize(long physicalAddress) { - return (recordSize, recordSize); + return (RecordSize, RecordSize); } public override (int actualSize, int allocatedSize, int keySize) GetRMWCopyDestinationRecordSize(ref Key key, ref Input input, ref Value value, ref RecordInfo recordInfo, TsavoriteSession tsavoriteSession) { - return (recordSize, recordSize, keySize); + return (RecordSize, RecordSize, KeySize); } - public override int GetAverageRecordSize() - { - return recordSize; - } + public override int GetAverageRecordSize() => RecordSize; - public override int GetFixedRecordSize() => recordSize; + public override int GetFixedRecordSize() => RecordSize; public override (int actualSize, int allocatedSize, int keySize) GetRMWInitialRecordSize(ref Key key, ref Input input, TsavoriteSession tsavoriteSession) { - return (recordSize, recordSize, keySize); + return (RecordSize, RecordSize, KeySize); } public override (int actualSize, int allocatedSize, int keySize) GetRecordSize(ref Key key, ref Value value) { - return (recordSize, recordSize, keySize); + return (RecordSize, RecordSize, KeySize); } - public override int GetValueLength(ref Value value) => valueSize; + public override int GetValueLength(ref Value value) => ValueSize; /// /// Dispose memory allocator @@ -136,7 +129,7 @@ public override void Dispose() public override AddressInfo* GetValueAddressInfo(long physicalAddress) { - return (AddressInfo*)((byte*)physicalAddress + RecordInfo.GetLength() + keySize); + return (AddressInfo*)((byte*)physicalAddress + RecordInfo.GetLength() + KeySize); } /// diff --git a/libs/storage/Tsavorite/cs/src/core/Allocator/GenericAllocator.cs b/libs/storage/Tsavorite/cs/src/core/Allocator/GenericAllocator.cs index 7caa7b1e2d..6319f4a769 100644 --- a/libs/storage/Tsavorite/cs/src/core/Allocator/GenericAllocator.cs +++ b/libs/storage/Tsavorite/cs/src/core/Allocator/GenericAllocator.cs @@ -45,16 +45,15 @@ internal sealed unsafe class GenericAllocator : AllocatorBase)); private readonly SerializerSettings SerializerSettings; private readonly bool keyBlittable = Utility.IsBlittable(); private readonly bool valueBlittable = Utility.IsBlittable(); - internal static int RecordSize => recordSize; // We do not support variable-length keys in GenericAllocator - private int keySize = Utility.GetSize(default(Key)); - private int valueSize = Utility.GetSize(default(Value)); + internal static int KeySize => Unsafe.SizeOf(); + internal static int ValueSize => Unsafe.SizeOf(); + internal static int RecordSize => Unsafe.SizeOf>(); private readonly OverflowPool[]> overflowPagePool; @@ -136,7 +135,7 @@ void ReturnPage(int index) public override void Initialize() { - Initialize(recordSize); + Initialize(RecordSize); } /// @@ -157,7 +156,7 @@ public override long GetStartLogicalAddress(long page) public override long GetFirstValidLogicalAddress(long page) { if (page == 0) - return (page << LogPageSizeBits) + recordSize; + return (page << LogPageSizeBits) + RecordSize; return page << LogPageSizeBits; } @@ -170,7 +169,7 @@ public override ref RecordInfo GetInfo(long physicalAddress) // Index of page within the circular buffer int pageIndex = (int)((physicalAddress >> LogPageSizeBits) & BufferSizeMask); - return ref values[pageIndex][offset / recordSize].info; + return ref values[pageIndex][offset / RecordSize].info; } public override ref RecordInfo GetInfoFromBytePointer(byte* ptr) @@ -186,7 +185,7 @@ public override ref Key GetKey(long physicalAddress) // Index of page within the circular buffer int pageIndex = (int)((physicalAddress >> LogPageSizeBits) & BufferSizeMask); - return ref values[pageIndex][offset / recordSize].key; + return ref values[pageIndex][offset / RecordSize].key; } public override ref Value GetValue(long physicalAddress) @@ -197,36 +196,36 @@ public override ref Value GetValue(long physicalAddress) // Index of page within the circular buffer int pageIndex = (int)((physicalAddress >> LogPageSizeBits) & BufferSizeMask); - return ref values[pageIndex][offset / recordSize].value; + return ref values[pageIndex][offset / RecordSize].value; } public override (int actualSize, int allocatedSize) GetRecordSize(long physicalAddress) { - return (recordSize, recordSize); + return (RecordSize, RecordSize); } - public override int GetValueLength(ref Value value) => valueSize; + public override int GetValueLength(ref Value value) => ValueSize; public override (int actualSize, int allocatedSize, int keySize) GetRMWCopyDestinationRecordSize(ref Key key, ref Input input, ref Value value, ref RecordInfo recordInfo, TsavoriteSession tsavoriteSession) { - return (recordSize, recordSize, keySize); + return (RecordSize, RecordSize, KeySize); } public override int GetAverageRecordSize() { - return recordSize; + return RecordSize; } - public override int GetFixedRecordSize() => recordSize; + public override int GetFixedRecordSize() => RecordSize; public override (int actualSize, int allocatedSize, int keySize) GetRMWInitialRecordSize(ref Key key, ref Input input, TsavoriteSession tsavoriteSession) { - return (recordSize, recordSize, keySize); + return (RecordSize, RecordSize, KeySize); } public override (int actualSize, int allocatedSize, int keySize) GetRecordSize(ref Key key, ref Value value) { - return (recordSize, recordSize, keySize); + return (RecordSize, RecordSize, KeySize); } internal override bool TryComplete() @@ -292,10 +291,10 @@ internal Record[] AllocatePage() return item; Record[] tmp; - if (PageSize % recordSize == 0) - tmp = new Record[PageSize / recordSize]; + if (PageSize % RecordSize == 0) + tmp = new Record[PageSize / RecordSize]; else - tmp = new Record[1 + (PageSize / recordSize)]; + tmp = new Record[1 + (PageSize / RecordSize)]; Array.Clear(tmp, 0, tmp.Length); return tmp; } @@ -303,7 +302,7 @@ internal Record[] AllocatePage() [MethodImpl(MethodImplOptions.AggressiveInlining)] internal long SnapToLogicalAddressBoundary(ref long logicalAddress) { - return logicalAddress = ((logicalAddress - Constants.kFirstValidAddress) / recordSize) * recordSize + Constants.kFirstValidAddress; + return logicalAddress = ((logicalAddress - Constants.kFirstValidAddress) / RecordSize) * RecordSize + Constants.kFirstValidAddress; } public override long GetPhysicalAddress(long logicalAddress) @@ -381,7 +380,7 @@ protected override void WriteAsyncToDevice internal override void ClearPage(long page, int offset) { - Array.Clear(values[page % BufferSize], offset / recordSize, values[page % BufferSize].Length - offset / recordSize); + Array.Clear(values[page % BufferSize], offset / RecordSize, values[page % BufferSize].Length - offset / RecordSize); } internal override void FreePage(long page) @@ -495,12 +494,12 @@ private void WriteAsync(long flushPage, ulong alignedDestinationAddres // Track the size to be written to the object log. long endPosition = 0; - for (int i = start / recordSize; i < end / recordSize; i++) + for (int i = start / RecordSize; i < end / RecordSize; i++) { if (!src[i].info.Invalid) { // Calculate the logical address of the 'values' page currently being written. - var address = (flushPage << LogPageSizeBits) + i * recordSize; + var address = (flushPage << LogPageSizeBits) + i * RecordSize; // Do not write v+1 records (e.g. during a checkpoint) if (address < fuzzyStartLogicalAddress || !src[i].info.IsInNewVersion) @@ -511,7 +510,7 @@ private void WriteAsync(long flushPage, ulong alignedDestinationAddres keySerializer.Serialize(ref src[i].key); // Store the key address into the 'buffer' AddressInfo image as an offset into 'ms'. - var key_address = GetKeyAddressInfo((long)(buffer.aligned_pointer + i * recordSize)); + var key_address = GetKeyAddressInfo((long)(buffer.aligned_pointer + i * RecordSize)); key_address->Address = pos; key_address->Size = (int)(ms.Position - pos); addr.Add((long)key_address); @@ -524,7 +523,7 @@ private void WriteAsync(long flushPage, ulong alignedDestinationAddres valueSerializer.Serialize(ref src[i].value); // Store the value address into the 'buffer' AddressInfo image as an offset into 'ms'. - var value_address = GetValueAddressInfo((long)(buffer.aligned_pointer + i * recordSize)); + var value_address = GetValueAddressInfo((long)(buffer.aligned_pointer + i * RecordSize)); value_address->Address = pos; value_address->Size = (int)(ms.Position - pos); addr.Add((long)value_address); @@ -534,13 +533,13 @@ private void WriteAsync(long flushPage, ulong alignedDestinationAddres else { // Mark v+1 records as invalid to avoid deserializing them on recovery - ref var record = ref Unsafe.AsRef>(buffer.aligned_pointer + i * recordSize); + ref var record = ref Unsafe.AsRef>(buffer.aligned_pointer + i * RecordSize); record.info.SetInvalid(); } } // If this record's serialized size surpassed ObjectBlockSize or it's the last record to be written, write to the object log. - if (endPosition > ObjectBlockSize || i == (end / recordSize) - 1) + if (endPosition > ObjectBlockSize || i == (end / RecordSize) - 1) { var memoryStreamActualLength = ms.Position; var memoryStreamTotalLength = (int)endPosition; @@ -573,7 +572,7 @@ private void WriteAsync(long flushPage, ulong alignedDestinationAddres ((AddressInfo*)address)->Address += _objAddr; // If we have not written all records, prepare for the next chunk of records to be written. - if (i < (end / recordSize) - 1) + if (i < (end / RecordSize) - 1) { // Create a new MemoryStream for the next chunk of records to be written. ms = new MemoryStream(); @@ -892,7 +891,7 @@ public void Deserialize(byte* raw, long ptr, long untilptr, Record[] while (ptr < untilptr) { ref Record record = ref Unsafe.AsRef>(raw + ptr); - src[ptr / recordSize].info = record.info; + src[ptr / RecordSize].info = record.info; if (!record.info.Invalid) { @@ -905,11 +904,11 @@ public void Deserialize(byte* raw, long ptr, long untilptr, Record[] stream.Seek(streamStartPos + key_addr->Address - start_addr, SeekOrigin.Begin); } - keySerializer.Deserialize(out src[ptr / recordSize].key); + keySerializer.Deserialize(out src[ptr / RecordSize].key); } else { - src[ptr / recordSize].key = record.key; + src[ptr / RecordSize].key = record.key; } if (!record.info.Tombstone) @@ -923,11 +922,11 @@ public void Deserialize(byte* raw, long ptr, long untilptr, Record[] stream.Seek(streamStartPos + value_addr->Address - start_addr, SeekOrigin.Begin); } - valueSerializer.Deserialize(out src[ptr / recordSize].value); + valueSerializer.Deserialize(out src[ptr / RecordSize].value); } else { - src[ptr / recordSize].value = record.value; + src[ptr / RecordSize].value = record.value; } } } @@ -1129,7 +1128,7 @@ internal void PopulatePage(byte* src, int required_bytes, ref Record { fixed (RecordInfo* pin = &destinationPage[0].info) { - Debug.Assert(required_bytes <= recordSize * destinationPage.Length); + Debug.Assert(required_bytes <= RecordSize * destinationPage.Length); Buffer.MemoryCopy(src, Unsafe.AsPointer(ref destinationPage[0]), required_bytes, required_bytes); } @@ -1174,10 +1173,10 @@ internal override void MemoryPageScan(long beginAddress, long endAddress, IObser { var page = (beginAddress >> LogPageSizeBits) % BufferSize; long pageStartAddress = beginAddress & ~PageSizeMask; - int start = (int)(beginAddress & PageSizeMask) / recordSize; - int count = (int)(endAddress - beginAddress) / recordSize; + int start = (int)(beginAddress & PageSizeMask) / RecordSize; + int count = (int)(endAddress - beginAddress) / RecordSize; int end = start + count; - using var iter = new MemoryPageScanIterator(values[page], start, end, pageStartAddress, recordSize); + using var iter = new MemoryPageScanIterator(values[page], start, end, pageStartAddress, RecordSize); Debug.Assert(epoch.ThisInstanceProtected()); try { diff --git a/libs/storage/Tsavorite/cs/src/core/Allocator/GenericFrame.cs b/libs/storage/Tsavorite/cs/src/core/Allocator/GenericFrame.cs index c0be63319b..00f117368a 100644 --- a/libs/storage/Tsavorite/cs/src/core/Allocator/GenericFrame.cs +++ b/libs/storage/Tsavorite/cs/src/core/Allocator/GenericFrame.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System; +using System.Runtime.CompilerServices; namespace Tsavorite.core { @@ -12,7 +13,7 @@ internal sealed class GenericFrame : IDisposable { private readonly Record[][] frame; public readonly int frameSize, pageSize; - private readonly int recordSize = Utility.GetSize(default(Record)); + private static int RecordSize => Unsafe.SizeOf>(); public GenericFrame(int frameSize, int pageSize) { @@ -24,10 +25,10 @@ public GenericFrame(int frameSize, int pageSize) public void Allocate(int index) { Record[] tmp; - if (pageSize % recordSize == 0) - tmp = new Record[pageSize / recordSize]; + if (pageSize % RecordSize == 0) + tmp = new Record[pageSize / RecordSize]; else - tmp = new Record[1 + (pageSize / recordSize)]; + tmp = new Record[1 + (pageSize / RecordSize)]; Array.Clear(tmp, 0, tmp.Length); frame[index] = tmp; } diff --git a/libs/storage/Tsavorite/cs/src/core/Index/Tsavorite/Implementation/Revivification/RevivificationManager.cs b/libs/storage/Tsavorite/cs/src/core/Index/Tsavorite/Implementation/Revivification/RevivificationManager.cs index b7d68ef090..aef44723a9 100644 --- a/libs/storage/Tsavorite/cs/src/core/Index/Tsavorite/Implementation/Revivification/RevivificationManager.cs +++ b/libs/storage/Tsavorite/cs/src/core/Index/Tsavorite/Implementation/Revivification/RevivificationManager.cs @@ -13,20 +13,17 @@ internal struct RevivificationManager internal RevivificationStats stats = new(); internal readonly bool IsEnabled = false; - internal readonly int FixedValueLength; + internal readonly int FixedValueLength => Unsafe.SizeOf(); internal bool restoreDeletedRecordsIfBinIsFull; internal bool useFreeRecordPoolForCTT; - internal readonly bool IsFixedLength => FixedValueLength != 0; + internal readonly bool IsFixedLength { get; } internal double revivifiableFraction; public RevivificationManager(TsavoriteKV store, bool isFixedLen, RevivificationSettings revivSettings, LogSettings logSettings) { - // Set these first in case revivification is not enabled; they still tell us not to expect fixed-length. - if (isFixedLen) - FixedValueLength = Utility.GetSize(default(Value)); - + IsFixedLength = isFixedLen; revivifiableFraction = revivSettings is null || revivSettings.RevivifiableFraction == RevivificationSettings.DefaultRevivifiableFraction ? logSettings.MutableFraction : revivSettings.RevivifiableFraction; diff --git a/libs/storage/Tsavorite/cs/src/core/Utilities/Utility.cs b/libs/storage/Tsavorite/cs/src/core/Utilities/Utility.cs index 51845c6e3f..53fba384e1 100644 --- a/libs/storage/Tsavorite/cs/src/core/Utilities/Utility.cs +++ b/libs/storage/Tsavorite/cs/src/core/Utilities/Utility.cs @@ -29,18 +29,6 @@ public readonly struct Empty /// public static class Utility { - /// - /// Get size of type - /// - /// - /// - /// - internal static unsafe int GetSize(this T value) - { - T[] arr = new T[2]; - return (int)((long)Unsafe.AsPointer(ref arr[1]) - (long)Unsafe.AsPointer(ref arr[0])); - } - /// /// Parse size in string notation into long. /// Examples: 4k, 4K, 4KB, 4 KB, 8m, 8MB, 12g, 12 GB, 16t, 16 TB, 32p, 32 PB. diff --git a/libs/storage/Tsavorite/cs/test/ExpirationTests.cs b/libs/storage/Tsavorite/cs/test/ExpirationTests.cs index 8240683109..343b25a629 100644 --- a/libs/storage/Tsavorite/cs/test/ExpirationTests.cs +++ b/libs/storage/Tsavorite/cs/test/ExpirationTests.cs @@ -60,8 +60,6 @@ public struct ExpirationInput internal TestOp testOp; } - private readonly int InputSize = Utility.GetSize(default(ExpirationInput)); - public struct ExpirationOutput { internal int retrievedValue;