From 808dcaf18e19778eeb5be3394d41467d5689b13f Mon Sep 17 00:00:00 2001 From: InCerry Date: Thu, 24 Nov 2022 21:31:04 +0800 Subject: [PATCH] Optimization performance --- benchmark/FasterKvCache.Benchmark/Program.cs | 2 +- .../ObjectFasterKvCache.cs | 1 + .../TFasterKvCache.cs | 1 + .../Abstractions/ClientSessionWrap.cs | 7 +- .../Abstractions/IFasterKvCacheSerializer.cs | 8 +- .../Abstractions/StoreFunctions.cs | 4 +- .../Abstractions/ValueWrapper.cs | 27 +++--- .../ServiceCollectionExtensions.cs | 1 + .../FasterKv.Cache.Core.csproj | 1 - src/FasterKv.Cache.Core/FasterKvCache.cs | 13 ++- .../FasterKvStore.TValue.cs | 4 +- .../Serializers/FasterKvSerializer.TValue.cs | 80 ++++++++--------- .../Serializers/FasterKvSerializer.cs | 63 ++++++++------ .../Serializers/StringSerializer.cs | 4 +- .../FasterKv.Cache.MessagePack.csproj | 1 + .../MessagePackFasterKvCacheSerializer.cs | 17 +++- .../SystemTextJsonFasterKvCacheSerializer.cs | 16 +++- .../KvStore/FasterKvStoreObjectTest.cs | 50 ++++++++++- .../KvStore/FasterKvStoreTest.Expiry.cs | 3 +- .../KvStore/FasterKvStoreTest.cs | 86 ++++++++++++++++++- 20 files changed, 281 insertions(+), 108 deletions(-) diff --git a/benchmark/FasterKvCache.Benchmark/Program.cs b/benchmark/FasterKvCache.Benchmark/Program.cs index 57cf66a..da1772b 100644 --- a/benchmark/FasterKvCache.Benchmark/Program.cs +++ b/benchmark/FasterKvCache.Benchmark/Program.cs @@ -22,7 +22,7 @@ public enum TestType #nullable disable public class FasterKvBenchmark { - private const long Count = 1000; + private const long Count = 10000; private static readonly Random _random = new Random(1024); private FasterKvCache _provider; private static readonly TimeSpan _default = TimeSpan.FromSeconds(30); diff --git a/sample/FasterKvCache.Sample.ConsoleApp/ObjectFasterKvCache.cs b/sample/FasterKvCache.Sample.ConsoleApp/ObjectFasterKvCache.cs index 4ef34bd..ee691a3 100644 --- a/sample/FasterKvCache.Sample.ConsoleApp/ObjectFasterKvCache.cs +++ b/sample/FasterKvCache.Sample.ConsoleApp/ObjectFasterKvCache.cs @@ -1,4 +1,5 @@ using FasterKv.Cache.Core; +using FasterKv.Cache.Core.Abstractions; using FasterKv.Cache.Core.Configurations; using FasterKv.Cache.MessagePack; diff --git a/sample/FasterKvCache.Sample.ConsoleApp/TFasterKvCache.cs b/sample/FasterKvCache.Sample.ConsoleApp/TFasterKvCache.cs index a30256b..42bdc8e 100644 --- a/sample/FasterKvCache.Sample.ConsoleApp/TFasterKvCache.cs +++ b/sample/FasterKvCache.Sample.ConsoleApp/TFasterKvCache.cs @@ -1,4 +1,5 @@ using FasterKv.Cache.Core; +using FasterKv.Cache.Core.Abstractions; using FasterKv.Cache.Core.Configurations; using FasterKv.Cache.MessagePack; diff --git a/src/FasterKv.Cache.Core/Abstractions/ClientSessionWrap.cs b/src/FasterKv.Cache.Core/Abstractions/ClientSessionWrap.cs index c71bb5d..a0f8c90 100644 --- a/src/FasterKv.Cache.Core/Abstractions/ClientSessionWrap.cs +++ b/src/FasterKv.Cache.Core/Abstractions/ClientSessionWrap.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Concurrent; using FASTER.core; -using FasterKv.Cache.Core.Abstractions; -namespace FasterKv.Cache.Core; +namespace FasterKv.Cache.Core.Abstractions; -public class ClientSessionWrap : IDisposable +internal sealed class ClientSessionWrap : IDisposable { public ClientSession, ValueWrapper, ValueWrapper, StoreContext>, StoreFunctions>> Session { get; } @@ -31,7 +30,7 @@ public void Dispose() } } -public class ClientSessionWrap : IDisposable +internal class ClientSessionWrap : IDisposable { public ClientSession, StoreFunctions> Session { get; } diff --git a/src/FasterKv.Cache.Core/Abstractions/IFasterKvCacheSerializer.cs b/src/FasterKv.Cache.Core/Abstractions/IFasterKvCacheSerializer.cs index 860a7b4..2437383 100644 --- a/src/FasterKv.Cache.Core/Abstractions/IFasterKvCacheSerializer.cs +++ b/src/FasterKv.Cache.Core/Abstractions/IFasterKvCacheSerializer.cs @@ -1,8 +1,12 @@ -namespace FasterKv.Cache.Core; +using System.IO; + +namespace FasterKv.Cache.Core; public interface IFasterKvCacheSerializer { string Name { get;} byte[] Serialize(TValue data); - TValue? Deserialize(byte[] serializerData); + TValue? Deserialize(byte[] bytes); + void Serialize(Stream stream, TValue data); + TValue? Deserialize(byte[] bytes, int length); } \ No newline at end of file diff --git a/src/FasterKv.Cache.Core/Abstractions/StoreFunctions.cs b/src/FasterKv.Cache.Core/Abstractions/StoreFunctions.cs index d4c5d07..c9efea6 100644 --- a/src/FasterKv.Cache.Core/Abstractions/StoreFunctions.cs +++ b/src/FasterKv.Cache.Core/Abstractions/StoreFunctions.cs @@ -2,7 +2,7 @@ namespace FasterKv.Cache.Core.Abstractions; -public class StoreContext +internal sealed class StoreContext { private Status _status; private TOutput? _output; @@ -20,7 +20,7 @@ internal void FinalizeRead(out Status status, out TOutput output) } } -public class StoreFunctions : SimpleFunctions> +internal sealed class StoreFunctions : SimpleFunctions> { public override void ReadCompletionCallback(ref TKey key, ref TOutput input, diff --git a/src/FasterKv.Cache.Core/Abstractions/ValueWrapper.cs b/src/FasterKv.Cache.Core/Abstractions/ValueWrapper.cs index 664a5f9..9b7e6bd 100644 --- a/src/FasterKv.Cache.Core/Abstractions/ValueWrapper.cs +++ b/src/FasterKv.Cache.Core/Abstractions/ValueWrapper.cs @@ -1,16 +1,16 @@ using System; -using MessagePack; +using System.Buffers; namespace FasterKv.Cache.Core; -public struct ValueWrapper +internal struct ValueWrapper { public ValueWrapper() { } - public ValueWrapper(T? data, DateTimeOffset? expiryTime = null) + public ValueWrapper(T? data, long? expiryTime = null) { ExpiryTime = expiryTime; Data = data; @@ -24,19 +24,19 @@ public ValueWrapper(T? data, DateTimeOffset? expiryTime = null) /// /// Expiry Time /// - public DateTimeOffset? ExpiryTime { get; set; } + public long? ExpiryTime { get; set; } /// /// HasExpired /// /// Now /// value has expired - public bool HasExpired(DateTimeOffset now) => now > ExpiryTime; + public bool HasExpired(DateTimeOffset now) => now.ToUnixTimeMilliseconds() > ExpiryTime; } -[MessagePackObject] -public class ValueWrapper +internal sealed class ValueWrapper { + internal int DataByteLength = 0; internal object? Data; public ValueWrapper() @@ -44,7 +44,7 @@ public ValueWrapper() } - public ValueWrapper(object? data, DateTimeOffset? expiryTime = null) + public ValueWrapper(object? data, long? expiryTime = null) { ExpiryTime = expiryTime; Data = data; @@ -53,13 +53,11 @@ public ValueWrapper(object? data, DateTimeOffset? expiryTime = null) /// /// Expiry Time /// - [Key(0)] - public DateTimeOffset? ExpiryTime { get; set; } + public long? ExpiryTime { get; set; } /// /// DataBytes /// - [Key(1)] public byte[]? DataBytes { get; set; } /// @@ -67,7 +65,7 @@ public ValueWrapper(object? data, DateTimeOffset? expiryTime = null) /// /// Now /// value has expired - public bool HasExpired(DateTimeOffset now) => now > ExpiryTime; + public bool HasExpired(DateTimeOffset now) => now.ToUnixTimeMilliseconds() > ExpiryTime; /// /// Get TValue From Data or DataBytes @@ -79,8 +77,11 @@ public ValueWrapper(object? data, DateTimeOffset? expiryTime = null) { if (DataBytes is not null) { - Data = serializer.Deserialize(DataBytes); + Data = serializer.Deserialize(DataBytes, DataByteLength); + var bytes = DataBytes; DataBytes = null; + DataByteLength = 0; + ArrayPool.Shared.Return(bytes); } return Data is null ? default : (TValue)Data; diff --git a/src/FasterKv.Cache.Core/Configurations/ServiceCollectionExtensions.cs b/src/FasterKv.Cache.Core/Configurations/ServiceCollectionExtensions.cs index 9b4f936..172af12 100644 --- a/src/FasterKv.Cache.Core/Configurations/ServiceCollectionExtensions.cs +++ b/src/FasterKv.Cache.Core/Configurations/ServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ using System; +using FasterKv.Cache.Core.Abstractions; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; diff --git a/src/FasterKv.Cache.Core/FasterKv.Cache.Core.csproj b/src/FasterKv.Cache.Core/FasterKv.Cache.Core.csproj index e5eae71..7640cdf 100644 --- a/src/FasterKv.Cache.Core/FasterKv.Cache.Core.csproj +++ b/src/FasterKv.Cache.Core/FasterKv.Cache.Core.csproj @@ -6,7 +6,6 @@ - diff --git a/src/FasterKv.Cache.Core/FasterKvCache.cs b/src/FasterKv.Cache.Core/FasterKvCache.cs index 409889b..eed4cae 100644 --- a/src/FasterKv.Cache.Core/FasterKvCache.cs +++ b/src/FasterKv.Cache.Core/FasterKvCache.cs @@ -175,7 +175,12 @@ public async Task SetAsync(string key, TValue? value, TimeSpan expiryTim private async Task SetInternalAsync(ClientSessionWrap sessionWrap, string key, TValue? value, CancellationToken cancellationToken, TimeSpan? expiryTime = null) { - var wrapper = new ValueWrapper(value, expiryTime.HasValue ? _systemClock.Now().Add(expiryTime.Value) : null); + var wrapper = new ValueWrapper(value, + expiryTime.HasValue + ? _systemClock.Now() + .Add(expiryTime.Value) + .ToUnixTimeMilliseconds() + : null); (await sessionWrap.Session.UpsertAsync(ref key, ref wrapper, token: cancellationToken) .ConfigureAwait(false)).Complete(); } @@ -184,7 +189,11 @@ private void SetInternal(ClientSessionWrap sessionWrap, string key, TVal TimeSpan? expiryTime = null) { var wrapper = new ValueWrapper(value, - expiryTime.HasValue ? _systemClock.Now().Add(expiryTime.Value) : null); + expiryTime.HasValue + ? _systemClock.Now() + .Add(expiryTime.Value) + .ToUnixTimeMilliseconds() + : null); sessionWrap.Session.Upsert(ref key, ref wrapper); } diff --git a/src/FasterKv.Cache.Core/FasterKvStore.TValue.cs b/src/FasterKv.Cache.Core/FasterKvStore.TValue.cs index f6d095b..451724e 100644 --- a/src/FasterKv.Cache.Core/FasterKvStore.TValue.cs +++ b/src/FasterKv.Cache.Core/FasterKvStore.TValue.cs @@ -171,7 +171,7 @@ private void SetInternal(ClientSessionWrap sessionWrap, string key, TVal TimeSpan? expiryTime = null) { var wrapper = new ValueWrapper(value, - expiryTime.HasValue ? _systemClock.Now().Add(expiryTime.Value) : null); + expiryTime.HasValue ? _systemClock.Now().Add(expiryTime.Value).ToUnixTimeMilliseconds() : null); sessionWrap.Session.Upsert(ref key, ref wrapper); } @@ -179,7 +179,7 @@ private async Task SetInternalAsync(ClientSessionWrap sessionWrap, strin CancellationToken cancellationToken, TimeSpan? expiryTime = null) { var wrapper = new ValueWrapper(value, - expiryTime.HasValue ? _systemClock.Now().Add(expiryTime.Value) : null); + expiryTime.HasValue ? _systemClock.Now().Add(expiryTime.Value).ToUnixTimeMilliseconds() : null); (await sessionWrap.Session.UpsertAsync(ref key, ref wrapper, token: cancellationToken) .ConfigureAwait(false)).Complete(); } diff --git a/src/FasterKv.Cache.Core/Serializers/FasterKvSerializer.TValue.cs b/src/FasterKv.Cache.Core/Serializers/FasterKvSerializer.TValue.cs index 34f61a7..991a47e 100644 --- a/src/FasterKv.Cache.Core/Serializers/FasterKvSerializer.TValue.cs +++ b/src/FasterKv.Cache.Core/Serializers/FasterKvSerializer.TValue.cs @@ -1,14 +1,10 @@ -using System; -using System.IO; +using System.Buffers; using FASTER.core; -using MessagePack; namespace FasterKv.Cache.Core.Serializers; -public class FasterKvSerializer : IObjectSerializer> +internal sealed class FasterKvSerializer : BinaryObjectSerializer> { - private Stream? _read; - private Stream? _write; private readonly IFasterKvCacheSerializer _serializer; public FasterKvSerializer(IFasterKvCacheSerializer serializer) @@ -16,50 +12,50 @@ public FasterKvSerializer(IFasterKvCacheSerializer serializer) _serializer = serializer.ArgumentNotNull(); } - public void BeginSerialize(Stream stream) + public override void Deserialize(out ValueWrapper obj) { - _write = stream; - } - - public void Serialize(ref ValueWrapper obj) - { - var pack = new DataPack + obj = new ValueWrapper(); + var etNullFlag = reader.ReadByte(); + if (etNullFlag == 1) { - ExpiryTime = obj.ExpiryTime, - SerializerData = _serializer.Serialize(obj.Data) - }; - MessagePackSerializer.Serialize(_write, pack); - } + obj.ExpiryTime = reader.ReadInt64(); + } - public void BeginDeserialize(Stream stream) - { - _read = stream; + var dataLength = reader.ReadInt32(); + var buffer = ArrayPool.Shared.Rent(dataLength); + try + { + _ = reader.Read(buffer, 0, dataLength); + obj.Data = _serializer.Deserialize(buffer, dataLength); + } + finally + { + ArrayPool.Shared.Return(buffer); + } } - public void Deserialize(out ValueWrapper obj) + public override void Serialize(ref ValueWrapper obj) { - var pack = MessagePackSerializer.Deserialize(_read); - obj = new ValueWrapper(_serializer.Deserialize(pack.SerializerData), pack.ExpiryTime); - } + if (obj.ExpiryTime is null) + { + // write Expiry Time is null flag + writer.Write((byte)0); + } + else + { + writer.Write((byte)1); + writer.Write(obj.ExpiryTime.Value); + } - public void EndSerialize() - { - } + var beforePos = writer.BaseStream.Position; + var dataPos = writer.BaseStream.Position = writer.BaseStream.Position += sizeof(int); + _serializer.Serialize(writer.BaseStream, obj.Data); + var afterPos = writer.BaseStream.Position; - public void EndDeserialize() - { - } - - [MessagePackObject] - public struct DataPack - { - /// - /// Expiry Time - /// - [Key(0)] - public DateTimeOffset? ExpiryTime { get; set; } + var length = (int)(afterPos - dataPos); + writer.BaseStream.Position = beforePos; - [Key(1)] - public byte[] SerializerData { get; set; } + writer.Write(length); + writer.BaseStream.Position = afterPos; } } \ No newline at end of file diff --git a/src/FasterKv.Cache.Core/Serializers/FasterKvSerializer.cs b/src/FasterKv.Cache.Core/Serializers/FasterKvSerializer.cs index b5cd8f9..c7a4ca2 100644 --- a/src/FasterKv.Cache.Core/Serializers/FasterKvSerializer.cs +++ b/src/FasterKv.Cache.Core/Serializers/FasterKvSerializer.cs @@ -1,13 +1,10 @@ -using System.IO; +using System.Buffers; using FASTER.core; -using MessagePack; namespace FasterKv.Cache.Core.Serializers; -public class FasterKvSerializer : IObjectSerializer +internal sealed class FasterKvSerializer : BinaryObjectSerializer { - private Stream? _read; - private Stream? _write; private readonly IFasterKvCacheSerializer _serializer; public FasterKvSerializer(IFasterKvCacheSerializer serializer) @@ -15,32 +12,42 @@ public FasterKvSerializer(IFasterKvCacheSerializer serializer) _serializer = serializer.ArgumentNotNull(); } - public void BeginSerialize(Stream stream) + public override void Deserialize(out ValueWrapper obj) { - _write = stream; + obj = new ValueWrapper(); + var etNullFlag = reader.ReadByte(); + if (etNullFlag == 1) + { + obj.ExpiryTime = reader.ReadInt64(); + } + + obj.DataByteLength = reader.ReadInt32(); + obj.DataBytes = ArrayPool.Shared.Rent(obj.DataByteLength); + _ = reader.Read(obj.DataBytes, 0, obj.DataByteLength); } - public void Serialize(ref ValueWrapper obj) - { - obj.DataBytes = _serializer.Serialize(obj.Data); - MessagePackSerializer.Serialize(_write, obj); - } - - public void BeginDeserialize(Stream stream) - { - _read = stream; - } - - public void Deserialize(out ValueWrapper obj) - { - obj = MessagePackSerializer.Deserialize(_read); - } - - public void EndSerialize() - { - } - - public void EndDeserialize() + public override void Serialize(ref ValueWrapper obj) { + if (obj.ExpiryTime is null) + { + // write Expiry Time is null flag + writer.Write((byte)0); + } + else + { + writer.Write((byte)1); + writer.Write(obj.ExpiryTime.Value); + } + + var beforePos = writer.BaseStream.Position; + var dataPos = writer.BaseStream.Position = writer.BaseStream.Position += sizeof(int); + _serializer.Serialize(writer.BaseStream, obj.Data); + var afterPos = writer.BaseStream.Position; + + var length = (int)(afterPos - dataPos); + writer.BaseStream.Position = beforePos; + + writer.Write(length); + writer.BaseStream.Position = afterPos; } } \ No newline at end of file diff --git a/src/FasterKv.Cache.Core/Serializers/StringSerializer.cs b/src/FasterKv.Cache.Core/Serializers/StringSerializer.cs index 39ab01e..e69d76c 100644 --- a/src/FasterKv.Cache.Core/Serializers/StringSerializer.cs +++ b/src/FasterKv.Cache.Core/Serializers/StringSerializer.cs @@ -1,8 +1,8 @@ using FASTER.core; -namespace FasterKv.Cache.Core; +namespace FasterKv.Cache.Core.Serializers; -public class StringSerializer : BinaryObjectSerializer +internal sealed class StringSerializer : BinaryObjectSerializer { public override void Deserialize(out string obj) { diff --git a/src/FasterKv.Cache.MessagePack/FasterKv.Cache.MessagePack.csproj b/src/FasterKv.Cache.MessagePack/FasterKv.Cache.MessagePack.csproj index 0d71e12..00c109a 100644 --- a/src/FasterKv.Cache.MessagePack/FasterKv.Cache.MessagePack.csproj +++ b/src/FasterKv.Cache.MessagePack/FasterKv.Cache.MessagePack.csproj @@ -9,6 +9,7 @@ + diff --git a/src/FasterKv.Cache.MessagePack/MessagePackFasterKvCacheSerializer.cs b/src/FasterKv.Cache.MessagePack/MessagePackFasterKvCacheSerializer.cs index 2e96764..cffcaa6 100644 --- a/src/FasterKv.Cache.MessagePack/MessagePackFasterKvCacheSerializer.cs +++ b/src/FasterKv.Cache.MessagePack/MessagePackFasterKvCacheSerializer.cs @@ -1,11 +1,14 @@ -using FasterKv.Cache.Core; +using System.Buffers; +using System.IO; +using FasterKv.Cache.Core; using MessagePack; namespace FasterKv.Cache.MessagePack; -public class MessagePackFasterKvCacheSerializer : IFasterKvCacheSerializer +public sealed class MessagePackFasterKvCacheSerializer : IFasterKvCacheSerializer { public string Name { get; set; } = "MessagePack"; + public byte[] Serialize(TValue data) { return MessagePackSerializer.Serialize(data); @@ -15,4 +18,14 @@ public TValue Deserialize(byte[] serializerData) { return MessagePackSerializer.Deserialize(serializerData); } + + public void Serialize(Stream stream, TValue data) + { + MessagePackSerializer.Serialize(stream, data); + } + + public TValue? Deserialize(byte[] serializerData, int length) + { + return MessagePackSerializer.Deserialize(new ReadOnlySequence(serializerData, 0, length)); + } } \ No newline at end of file diff --git a/src/FasterKv.Cache.SystemTextJson/SystemTextJsonFasterKvCacheSerializer.cs b/src/FasterKv.Cache.SystemTextJson/SystemTextJsonFasterKvCacheSerializer.cs index e95c6f1..4091c05 100644 --- a/src/FasterKv.Cache.SystemTextJson/SystemTextJsonFasterKvCacheSerializer.cs +++ b/src/FasterKv.Cache.SystemTextJson/SystemTextJsonFasterKvCacheSerializer.cs @@ -1,8 +1,10 @@ -using FasterKv.Cache.Core; +using System; +using System.IO; +using FasterKv.Cache.Core; namespace FasterKv.Cache.SystemTextJson; -public class SystemTextJsonFasterKvCacheSerializer : IFasterKvCacheSerializer +public sealed class SystemTextJsonFasterKvCacheSerializer : IFasterKvCacheSerializer { public string Name { get; set; } = "SystemTextJson"; public byte[] Serialize(TValue data) @@ -14,4 +16,14 @@ public byte[] Serialize(TValue data) { return System.Text.Json.JsonSerializer.Deserialize(serializerData); } + + public void Serialize(Stream stream, TValue data) + { + System.Text.Json.JsonSerializer.Serialize(stream, data); + } + + public TValue? Deserialize(byte[] serializerData, int length) + { + return System.Text.Json.JsonSerializer.Deserialize(new Span(serializerData,0, length)); + } } \ No newline at end of file diff --git a/tests/FasterKv.Cache.Core.Tests/KvStore/FasterKvStoreObjectTest.cs b/tests/FasterKv.Cache.Core.Tests/KvStore/FasterKvStoreObjectTest.cs index f6c754e..f1818bc 100644 --- a/tests/FasterKv.Cache.Core.Tests/KvStore/FasterKvStoreObjectTest.cs +++ b/tests/FasterKv.Cache.Core.Tests/KvStore/FasterKvStoreObjectTest.cs @@ -4,7 +4,7 @@ namespace FasterKv.Cache.Core.Tests.KvStore; -public class FasterKvStoreObjectTest +public class FasterKvStoreObjectTest : IDisposable { private readonly FasterKvCache _fasterKv; @@ -174,6 +174,28 @@ public void Set_Big_DataSize_Should_Success() } } + [Fact] + public void Set_Big_DataSize_With_ExpiryTime_Should_Success() + { + int nums = 1000; + for (int i = 0; i < nums; i++) + { + _fasterKv.Set($"big_data_{i}", new Data + { + One = i.ToString(), + Two = i + }, TimeSpan.FromMinutes(5)); + } + + for (int i = 0; i < nums; i++) + { + var value = _fasterKv.Get($"big_data_{i}"); + Assert.NotNull(value); + Assert.Equal(i.ToString(), value!.One); + Assert.Equal(i, value.Two); + } + } + [Fact] public void Set_Big_DataSize_And_Repeat_Reading_Should_Success() { @@ -198,5 +220,29 @@ public void Set_Big_DataSize_And_Repeat_Reading_Should_Success() Assert.Equal(0.ToString(), value!.One); Assert.Equal(0, value.Two); } - + + [Fact] + public void Set_Big_Value_Should_Success() + { + // 8MB Value + var bigValues = Enumerable.Range(0, 8 * 1024 * 1024).Select(i => (byte) i).ToArray(); + int nums = 200; + for (int i = 0; i < nums; i++) + { + _fasterKv.Set($"big_value_{i}", bigValues); + } + + for (int i = 0; i < nums; i++) + { + var result = _fasterKv.Get($"big_value_{i}"); + + Assert.NotNull(result); + Assert.True(bigValues.SequenceEqual(result!)); + } + } + + public void Dispose() + { + _fasterKv.Dispose(); + } } \ No newline at end of file diff --git a/tests/FasterKv.Cache.Core.Tests/KvStore/FasterKvStoreTest.Expiry.cs b/tests/FasterKv.Cache.Core.Tests/KvStore/FasterKvStoreTest.Expiry.cs index 9968c14..6f20097 100644 --- a/tests/FasterKv.Cache.Core.Tests/KvStore/FasterKvStoreTest.Expiry.cs +++ b/tests/FasterKv.Cache.Core.Tests/KvStore/FasterKvStoreTest.Expiry.cs @@ -1,4 +1,5 @@ -using FasterKv.Cache.Core.Configurations; +using FasterKv.Cache.Core.Abstractions; +using FasterKv.Cache.Core.Configurations; using FasterKv.Cache.MessagePack; namespace FasterKv.Cache.Core.Tests.KvStore; diff --git a/tests/FasterKv.Cache.Core.Tests/KvStore/FasterKvStoreTest.cs b/tests/FasterKv.Cache.Core.Tests/KvStore/FasterKvStoreTest.cs index 5c690f1..8bf7e2b 100644 --- a/tests/FasterKv.Cache.Core.Tests/KvStore/FasterKvStoreTest.cs +++ b/tests/FasterKv.Cache.Core.Tests/KvStore/FasterKvStoreTest.cs @@ -1,11 +1,12 @@ -using FasterKv.Cache.Core.Configurations; +using FasterKv.Cache.Core.Abstractions; +using FasterKv.Cache.Core.Configurations; using FasterKv.Cache.MessagePack; using FasterKv.Cache.SystemTextJson; using MessagePack; namespace FasterKv.Cache.Core.Tests.KvStore; -public class FasterKvStoreTest +public class FasterKvStoreTest : IDisposable { private readonly FasterKvCache _fasterKv; @@ -198,6 +199,85 @@ public async Task SetAsync_Big_DataSize_Should_Success() } } + [Fact] + public void Set_Big_DataSize_With_ExpiryTime_Should_Success() + { + int nums = 1000; + for (int i = 0; i < nums; i++) + { + _fasterKv.Set($"big_data_{i}", new Data + { + One = i.ToString(), + Two = i + }, TimeSpan.FromMinutes(5)); + } + + for (int i = 0; i < nums; i++) + { + var value = _fasterKv.Get($"big_data_{i}"); + Assert.NotNull(value); + Assert.Equal(i.ToString(), value!.One); + Assert.Equal(i, value.Two); + } + } + + [Fact] + public void Set_Big_DataSize_And_Repeat_Reading_Should_Success() + { + int nums = 1000; + for (int i = 0; i < nums; i++) + { + _fasterKv.Set($"big_value_{i}", new Data + { + One = i.ToString(), + Two = i + }); + } + + var value = _fasterKv.Get($"big_value_{0}"); + Assert.NotNull(value); + Assert.Equal(0.ToString(), value!.One); + Assert.Equal(0, value.Two); + + + value = _fasterKv.Get($"big_value_{0}"); + Assert.NotNull(value); + Assert.Equal(0.ToString(), value!.One); + Assert.Equal(0, value.Two); + } + + [Fact] + public void Set_Big_Value_Should_Success() + { + // 4MB value + var bigValues = Enumerable.Range(0, 4 * 1024 * 1024).Select(i => (byte) i).ToArray(); + + int nums = 200; + for (int i = 0; i < nums; i++) + { + _fasterKv.Set($"big_value_{i}", new Data + { + One = i.ToString(), + Two = i, + Three = bigValues + }); + } + + for (int i = 0; i < nums; i++) + { + var result = _fasterKv.Get($"big_value_{i}"); + + Assert.NotNull(result?.Three); + Assert.Equal(i.ToString(), result!.One); + Assert.Equal(i, result.Two); + Assert.True(bigValues.SequenceEqual(result.Three!)); + } + } + + public void Dispose() + { + _fasterKv.Dispose(); + } } [MessagePackObject] @@ -206,6 +286,8 @@ public class Data [Key(0)] public string? One { get; set; } [Key(1)] public long Two { get; set; } + + [Key(2)] public byte[]? Three { get; set; } public override bool Equals(object? obj) {