Skip to content

Commit

Permalink
Allow Upsert to configure value length based on Input, in Tsavorite. (#…
Browse files Browse the repository at this point in the history
…714)

* Allow Upsert to configure value length based on Input, in Tsavorite.

* fix to actually call api during creation of new record in upsert

* fix test

* fix ycsb value length
  • Loading branch information
badrishc authored Oct 10, 2024
1 parent ace7cb6 commit e3c8a20
Show file tree
Hide file tree
Showing 20 changed files with 79 additions and 2 deletions.
3 changes: 3 additions & 0 deletions libs/server/Storage/Functions/MainStore/VarLenInputMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -255,5 +255,8 @@ public int GetRMWModifiedValueLength(ref SpanByte t, ref SpanByte input)

return sizeof(int) + input.Length - RespInputHeader.Size;
}

public int GetUpsertValueLength(ref SpanByte t, ref SpanByte input)
=> t.TotalSize;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,10 @@ public int GetRMWInitialValueLength(ref ObjectInput input)
{
throw new GarnetException("GetRMWInitialValueLength is not available on the object store");
}

public int GetUpsertValueLength(ref IGarnetObject value, ref ObjectInput input)
{
throw new GarnetException("GetUpsertInitialValueLength is not available on the object store");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public void PostInitialUpdater(ref Key key, ref Input input, ref Value value, re

public int GetRMWModifiedValueLength(ref Value value, ref Input input) => 0;
public int GetRMWInitialValueLength(ref Input input) => 0;
public int GetUpsertValueLength(ref Value value, ref Input input) => Value.Size;

public void PostSingleDeleter(ref Key key, ref DeleteInfo deleteInfo) { }

Expand Down
2 changes: 2 additions & 0 deletions libs/storage/Tsavorite/cs/benchmark/YCSB.benchmark/Value.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ namespace Tsavorite.benchmark
[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct Value
{
public const int Size = 8;

[FieldOffset(0)]
public long value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ public void RMWCompletionCallback(ref TKey key, ref TInput input, ref TOutput ou

public int GetRMWModifiedValueLength(ref TValue value, ref TInput input) => 0;
public int GetRMWInitialValueLength(ref TInput input) => 0;
public int GetUpsertValueLength(ref TValue value, ref TInput input) => 0;

public void ConvertOutputToHeap(ref TInput input, ref TOutput output) { }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ public readonly (int actualSize, int allocatedSize, int keySize) GetRMWInitialRe
where TSessionFunctionsWrapper : IVariableLengthInput<TValue, TInput>
=> BlittableAllocatorImpl<TKey, TValue, TStoreFunctions>.GetRMWInitialRecordSize(ref key, ref input, sessionFunctions);

/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly (int actualSize, int allocatedSize, int keySize) GetUpsertRecordSize<TInput, TSessionFunctionsWrapper>(ref TKey key, ref TValue value, ref TInput input, TSessionFunctionsWrapper sessionFunctions)
where TSessionFunctionsWrapper : IVariableLengthInput<TValue, TInput>
=> BlittableAllocatorImpl<TKey, TValue, TStoreFunctions>.GetUpsertRecordSize(ref key, ref value, ref input, sessionFunctions);

/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly (int actualSize, int allocatedSize, int keySize) GetRecordSize(ref TKey key, ref TValue value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ public static (int actualSize, int allocatedSize, int keySize) GetRMWInitialReco
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static (int actualSize, int allocatedSize, int keySize) GetRecordSize(ref TKey key, ref TValue value) => (RecordSize, RecordSize, KeySize);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static (int actualSize, int allocatedSize, int keySize) GetUpsertRecordSize<TInput, TSessionFunctionsWrapper>(ref TKey key, ref TValue value, ref TInput input, TSessionFunctionsWrapper sessionFunctions)
=> (RecordSize, RecordSize, KeySize);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetValueLength(ref TValue value) => ValueSize;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ public readonly (int actualSize, int allocatedSize, int keySize) GetRMWInitialRe
where TSessionFunctionsWrapper : IVariableLengthInput<TValue, TInput>
=> _this.GetRMWInitialRecordSize(ref key, ref input, sessionFunctions);

/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly (int actualSize, int allocatedSize, int keySize) GetUpsertRecordSize<TInput, TSessionFunctionsWrapper>(ref TKey key, ref TValue value, ref TInput input, TSessionFunctionsWrapper sessionFunctions)
where TSessionFunctionsWrapper : IVariableLengthInput<TValue, TInput>
=> _this.GetUpsertRecordSize(ref key, ref value, ref input, sessionFunctions);

/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly (int actualSize, int allocatedSize, int keySize) GetRecordSize(ref TKey key, ref TValue value) => _this.GetRecordSize(ref key, ref value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ internal ref TValue GetValue(long physicalAddress)

internal (int actualSize, int allocatedSize, int keySize) GetRecordSize(ref TKey key, ref TValue value) => (RecordSize, RecordSize, KeySize);

internal (int actualSize, int allocatedSize, int keySize) GetUpsertRecordSize<TInput, TSessionFunctionsWrapper>(ref TKey key, ref TValue value, ref TInput input, TSessionFunctionsWrapper sessionFunctions)
=> (RecordSize, RecordSize, KeySize);

internal override bool TryComplete()
{
var b1 = objectLogDevice.TryComplete();
Expand Down
4 changes: 4 additions & 0 deletions libs/storage/Tsavorite/cs/src/core/Allocator/IAllocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ AllocatorBase<TKey, TValue, TStoreFunctions, TAllocator> GetBase<TAllocator>()
(int actualSize, int allocatedSize, int keySize) GetRMWInitialRecordSize<TInput, TSessionFunctionsWrapper>(ref TKey key, ref TInput input, TSessionFunctionsWrapper sessionFunctions)
where TSessionFunctionsWrapper : IVariableLengthInput<TValue, TInput>;

/// <summary>Get record size required for the given <paramref name="key"/>, <paramref name="value"/>, and <paramref name="input"/></summary>
(int actualSize, int allocatedSize, int keySize) GetUpsertRecordSize<TInput, TSessionFunctionsWrapper>(ref TKey key, ref TValue value, ref TInput input, TSessionFunctionsWrapper sessionFunctions)
where TSessionFunctionsWrapper : IVariableLengthInput<TValue, TInput>;

/// <summary>Get record size required for the given <paramref name="key"/> and <paramref name="value"/></summary>
(int actualSize, int allocatedSize, int keySize) GetRecordSize(ref TKey key, ref TValue value);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ public readonly (int actualSize, int allocatedSize, int keySize) GetRMWInitialRe
where TSessionFunctionsWrapper : IVariableLengthInput<SpanByte, TInput>
=> _this.GetRMWInitialRecordSize(ref key, ref input, sessionFunctions);

/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly (int actualSize, int allocatedSize, int keySize) GetUpsertRecordSize<TInput, TSessionFunctionsWrapper>(ref SpanByte key, ref SpanByte value, ref TInput input, TSessionFunctionsWrapper sessionFunctions)
where TSessionFunctionsWrapper : IVariableLengthInput<SpanByte, TInput>
=> _this.GetUpsertRecordSize(ref key, ref value, ref input, sessionFunctions);

/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly (int actualSize, int allocatedSize, int keySize) GetRecordSize(ref SpanByte key, ref SpanByte value) => _this.GetRecordSize(ref key, ref value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,14 @@ public int GetRequiredRecordSize(long physicalAddress, int availableBytes)
return (actualSize, RoundUp(actualSize, Constants.kRecordAlignment), keySize);
}

public (int actualSize, int allocatedSize, int keySize) GetUpsertRecordSize<TInput, TSessionFunctionsWrapper>(ref SpanByte key, ref SpanByte value, ref TInput input, TSessionFunctionsWrapper sessionFunctions)
where TSessionFunctionsWrapper : IVariableLengthInput<SpanByte, TInput>
{
int keySize = key.TotalSize;
var actualSize = RecordInfo.GetLength() + RoundUp(keySize, Constants.kRecordAlignment) + sessionFunctions.GetUpsertValueLength(ref value, ref input);
return (actualSize, RoundUp(actualSize, Constants.kRecordAlignment), keySize);
}

public (int actualSize, int allocatedSize, int keySize) GetRecordSize(ref SpanByte key, ref SpanByte value)
{
int keySize = key.TotalSize;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ public void UnlockTransientShared(ref TKey key, ref OperationStackContext<TKey,
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetRMWModifiedValueLength(ref TValue t, ref TInput input) => _clientSession.functions.GetRMWModifiedValueLength(ref t, ref input);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetUpsertValueLength(ref TValue t, ref TInput input) => _clientSession.functions.GetUpsertValueLength(ref t, ref input);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public IHeapContainer<TInput> GetHeapContainer(ref TInput input)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public void RMWCompletionCallback(ref TKey key, ref TInput input, ref TOutput ou

public int GetRMWModifiedValueLength(ref TValue value, ref TInput input) => 0;
public int GetRMWInitialValueLength(ref TInput input) => 0;
public int GetUpsertValueLength(ref TValue value, ref TInput input) => _functions.GetUpsertValueLength(ref value, ref input);

/// <summary>
/// No reads during compaction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ public interface ISessionFunctions<TKey, TValue, TInput, TOutput, TContext>
/// Initial expected length of value object when populated by RMW using given input
/// </summary>
int GetRMWInitialValueLength(ref TInput input);

/// <summary>
/// Length of resulting value object when performing Upsert of value using given input
/// </summary>
int GetUpsertValueLength(ref TValue value, ref TInput input);
#endregion Variable-length value size

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public virtual void RMWCompletionCallback(ref TKey key, ref TInput input, ref TO
public virtual int GetRMWModifiedValueLength(ref TValue value, ref TInput input) => throw new TsavoriteException("GetRMWModifiedValueLength is only available for SpanByte Functions");
/// <inheritdoc/>
public virtual int GetRMWInitialValueLength(ref TInput input) => throw new TsavoriteException("GetRMWInitialValueLength is only available for SpanByte Functions");
/// <inheritdoc/>
public virtual int GetUpsertValueLength(ref TValue value, ref TInput input) => throw new TsavoriteException("GetUpsertValueLength is only available for SpanByte Functions");

/// <inheritdoc/>
public virtual void ConvertOutputToHeap(ref TInput input, ref TOutput output) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ private OperationStatus CreateNewRecordUpsert<TInput, TOutput, TContext, TSessio
ref OperationStackContext<TKey, TValue, TStoreFunctions, TAllocator> stackCtx, ref RecordInfo srcRecordInfo)
where TSessionFunctionsWrapper : ISessionFunctionsWrapper<TKey, TValue, TInput, TOutput, TContext, TStoreFunctions, TAllocator>
{
var (actualSize, allocatedSize, keySize) = hlog.GetRecordSize(ref key, ref value); // Input is not included in record-length calculations for Upsert
var (actualSize, allocatedSize, keySize) = hlog.GetUpsertRecordSize(ref key, ref value, ref input, sessionFunctions);
AllocateOptions allocOptions = new()
{
Recycle = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,13 @@ public interface IVariableLengthInput<TValue, TInput>
/// <param name="input"></param>
/// <returns></returns>
int GetRMWInitialValueLength(ref TInput input);

/// <summary>
/// Length of value object, when populated by Upsert using given value and input
/// </summary>
/// <param name="value"></param>
/// <param name="input"></param>
/// <returns></returns>
int GetUpsertValueLength(ref TValue value, ref TInput input);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System.Buffers;
using System.Runtime.CompilerServices;
using static Tsavorite.core.Utility;

namespace Tsavorite.core
{
Expand Down Expand Up @@ -125,5 +124,12 @@ public override int GetRMWModifiedValueLength(ref SpanByte t, ref SpanByte input

/// <inheritdoc/>
public override int GetRMWInitialValueLength(ref SpanByte input) => input.TotalSize;

/// <summary>
/// Length of resulting object when doing Upsert with given value and input. Here we set the length to the
/// length of the provided value, ignoring input. You can provide a custom implementation for other cases.
/// </summary>
public override int GetUpsertValueLength(ref SpanByte t, ref SpanByte input)
=> t.TotalSize;
}
}
3 changes: 3 additions & 0 deletions libs/storage/Tsavorite/cs/test/ExpirationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,9 @@ public override void ReadCompletionCallback(ref SpanByte key, ref ExpirationInpu
/// <inheritdoc/>
public override int GetRMWInitialValueLength(ref ExpirationInput input) => MinValueLen;

/// <inheritdoc/>
public override int GetUpsertValueLength(ref SpanByte value, ref ExpirationInput input) => value.TotalSize;

// Read functions
public override unsafe bool SingleReader(ref SpanByte key, ref ExpirationInput input, ref SpanByte value, ref ExpirationOutput output, ref ReadInfo readInfo)
{
Expand Down

0 comments on commit e3c8a20

Please sign in to comment.