From da7683aaf62ca799edda98b477b7bc4ba3350a7e Mon Sep 17 00:00:00 2001 From: InCerry Date: Mon, 21 Nov 2022 21:27:30 +0800 Subject: [PATCH] add sample,benchmark and readme --- FasterKv.Cache.sln | 23 ++ README.md | 240 ++++++++++++++++++ .../FasterKvCache.Benchmark.csproj | 20 ++ benchmark/FasterKvCache.Benchmark/Program.cs | 128 ++++++++++ docs/assets/arch.png | Bin 0 -> 96519 bytes .../FasterKvCache.Sample.ConsoleApp.csproj | 15 ++ .../ObjectFasterKvCache.cs | 52 ++++ .../Program.cs | 4 + .../TFasterKvCache.cs | 49 ++++ .../Configurations/FasterKvCacheOptions.cs | 2 +- .../FasterKvCacheDITest.cs | 38 ++- 11 files changed, 548 insertions(+), 23 deletions(-) create mode 100644 README.md create mode 100644 benchmark/FasterKvCache.Benchmark/FasterKvCache.Benchmark.csproj create mode 100644 benchmark/FasterKvCache.Benchmark/Program.cs create mode 100644 docs/assets/arch.png create mode 100644 sample/FasterKvCache.Sample.ConsoleApp/FasterKvCache.Sample.ConsoleApp.csproj create mode 100644 sample/FasterKvCache.Sample.ConsoleApp/ObjectFasterKvCache.cs create mode 100644 sample/FasterKvCache.Sample.ConsoleApp/Program.cs create mode 100644 sample/FasterKvCache.Sample.ConsoleApp/TFasterKvCache.cs diff --git a/FasterKv.Cache.sln b/FasterKv.Cache.sln index ca05d73..69410db 100644 --- a/FasterKv.Cache.sln +++ b/FasterKv.Cache.sln @@ -12,6 +12,19 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FasterKv.Cache.MessagePack" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FasterKv.Cache.SystemTextJson", "src\FasterKv.Cache.SystemTextJson\FasterKv.Cache.SystemTextJson.csproj", "{F5940765-9AE9-44E9-8847-AE1693E6C92B}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Items", "Items", "{E26D3646-0BC7-43AA-97D0-FC51693BFBFD}" + ProjectSection(SolutionItems) = preProject + README.md = README.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{A63977CD-B7C0-4963-857D-2DFCA8A28110}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FasterKvCache.Sample.ConsoleApp", "sample\FasterKvCache.Sample.ConsoleApp\FasterKvCache.Sample.ConsoleApp.csproj", "{5D6CFE59-B3FB-418B-A833-29861CDCFA1D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmark", "benchmark", "{814EFFB2-4634-47EC-82AF-0BC0D03C193E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FasterKvCache.Benchmark", "benchmark\FasterKvCache.Benchmark\FasterKvCache.Benchmark.csproj", "{488C3EBF-043B-4F49-8295-727A89607ABD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -34,11 +47,21 @@ Global {F5940765-9AE9-44E9-8847-AE1693E6C92B}.Debug|Any CPU.Build.0 = Debug|Any CPU {F5940765-9AE9-44E9-8847-AE1693E6C92B}.Release|Any CPU.ActiveCfg = Release|Any CPU {F5940765-9AE9-44E9-8847-AE1693E6C92B}.Release|Any CPU.Build.0 = Release|Any CPU + {5D6CFE59-B3FB-418B-A833-29861CDCFA1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D6CFE59-B3FB-418B-A833-29861CDCFA1D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D6CFE59-B3FB-418B-A833-29861CDCFA1D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D6CFE59-B3FB-418B-A833-29861CDCFA1D}.Release|Any CPU.Build.0 = Release|Any CPU + {488C3EBF-043B-4F49-8295-727A89607ABD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {488C3EBF-043B-4F49-8295-727A89607ABD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {488C3EBF-043B-4F49-8295-727A89607ABD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {488C3EBF-043B-4F49-8295-727A89607ABD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {FFDB364D-A31F-44EB-AAED-2823F39E4D48} = {390A098B-4FD2-419A-A2F6-77B6D1B19BFB} {72445807-EB50-41D1-BEFE-1805B4AD0408} = {FFC77C65-4B97-4712-9FA6-65055A0E3CE2} {B04D6116-8FE3-439B-B95A-8617A7777558} = {390A098B-4FD2-419A-A2F6-77B6D1B19BFB} {F5940765-9AE9-44E9-8847-AE1693E6C92B} = {390A098B-4FD2-419A-A2F6-77B6D1B19BFB} + {5D6CFE59-B3FB-418B-A833-29861CDCFA1D} = {A63977CD-B7C0-4963-857D-2DFCA8A28110} + {488C3EBF-043B-4F49-8295-727A89607ABD} = {814EFFB2-4634-47EC-82AF-0BC0D03C193E} EndGlobalSection EndGlobal diff --git a/README.md b/README.md new file mode 100644 index 0000000..2fc23bd --- /dev/null +++ b/README.md @@ -0,0 +1,240 @@ +# FasterKv.Cache + +FasterKv.Cache是一个基于微软FasterKv封装的进程内混合缓存库(内存+磁盘)。FasterKv它可以承载大于机器内存的Key-Value数据库,并且有着远超其它内存+磁盘数据库的性能。不过使用起来比较繁琐,对新人不友好,于是FasterKv.Cache在它的基础上进行了一层封装,让我们能更简单的处理缓存。 + +![arch](docs/assets/arch.png) + +| 适用场景 | 不适用场景 | 原因 | +| ------------------------------------------------------------ | -------------------------------------------- | ------------------------------------------------------------ | +| 缓存数据量大,并且有降低内存使用的需求 | 数据量小,或者有钞能力 | 如果数据量小和有钞能力,直接使用内存缓存才是性能最好的。 | +| 有明显的冷、热数据,数据能存储在内存中 | 没有冷热数据,完全随机访问 | 如果完全随机访问,意味着内存缓存将无效,每次读盘损耗会比较大 | +| 对于缓存没有非常严格的延时要求,几百us无所谓 | 对于缓存有高要求,不能接受波动 | 如果对于缓存有非常高的要求,几百微秒延时都不能忍受,那解决方案还是内存缓存 | +| 1.没有缓存非常大的数据。 2.有非常大的数据,但是经常访问,可以利用缓存。2.非常大的数据很少访问,对延时不敏感 | 有非常大的数据,且随机访问,并且延时非常敏感 | 如果有非常大的数据缓存,比如超过内存和ReadCache大小的,那么性能会变得比较差,想要解决它,只有钞能力。 | + +笔者之前给EasyCaching提交了FasterKv的实现,但是由于有一些EasyCaching的高级功能在FasterKv上无法高性能的实现,所以单独创建了这个库,提供高性能和最基本的API实现;如果大家有使用EasyCaching那么一样可以直接使用EasyCaching.FasterKv。 + +## NuGet 软件包 + +| 软件包名 | 版本 | 备注 | +|-----------------------------------------------------------------------------------------------|-----------|-------------------------------------------------------------------------------------------| +| [FasterKv.Cache.Core](https://www.nuget.org/packages/FasterKv.Cache.Core) | 1.0.0-rc1 | 缓存核心包,包含FasterKvCache主要的API | +| [FasterKv.Cache.MessagePack](https://www.nuget.org/packages/FasterKv.Cache.MessagePack) | 1.0.0-rc1 | 基于MessagePack的磁盘序列化包,它具有着非常好的性能,但是需要注意它稍微有一点使用门槛,大家可以看它的文档。 | +| [FasterKv.Cache.SystemTextJson](https://www.nuget.org/packages/FasterKv.Cache.SystemTextJson) | 1.0.0-rc1 | 基于System.Text.Json的磁盘序列化包,它是.NET平台上性能最好JSON序列化封装,但是比MessagePack差。不过它易用性非常好,无需对缓存实体进行单独配置。 | + +## 使用 + +### 直接使用 + +我们可以直接通过`new FasterKvCache(...)`的方式使用它,目前它只支持基本的三种操作`Get`、`Set`、`Delete`。为了方便使用和性能的考虑,我们将FasterKvCache分为两种API风格,一种是通用对象风格,一种是泛型风格。 + +* 通用对象:直接使用`new FasterKvCache(...)`创建,可以存放任意类型的Value。它底层使用`object`类型存储,所以内存缓冲内访问值类型对象会有装箱和拆箱的开销。 +* 泛型:需要使用`new FasterKvCache(...)`创建,只能存放`T`类型的Value。它底层使用`T`类型存储,所以内存缓冲内不会有任何开销。 + +当然如果内存缓冲不够,对应的Value被淘汰到磁盘上,那么同样都会有读磁盘、序列化和反序列化开销。 + +### 通用对象版本 + +代码如下所示,同一个cache实例可以添加任意类型: + +```cs +using FasterKv.Cache.Core; +using FasterKv.Cache.Core.Configurations; +using FasterKv.Cache.MessagePack; + +// create a FasterKvCache +var cache = new FasterKv.Cache.Core.FasterKvCache("MyCache", + new DefaultSystemClock(), + new FasterKvCacheOptions(), + new IFasterKvCacheSerializer[] + { + new MessagePackFasterKvCacheSerializer + { + Name = "MyCache" + } + }, + null); + +var key = Guid.NewGuid().ToString("N"); + +// sync +// set key and value with expiry time +cache.Set(key, "my cache sync", TimeSpan.FromMinutes(5)); + +// get +var result = cache.Get(key); +Console.WriteLine(result); + +// delete +cache.Delete(key); + +// async +// set +await cache.SetAsync(key, "my cache async"); + +// get +result = await cache.GetAsync(key); +Console.WriteLine(result); + +// delete +await cache.DeleteAsync(key); + +// set other type object +cache.Set(key, new DateTime(2022,2,22)); +Console.WriteLine(cache.Get(key)); +``` + +输出结果如下所示: + +```sh +my cache sync +my cache async +2022/2/22 0:00:00 +``` + +### 泛型版本 + +泛型版本的话性能最好,但是它只允许添加一个类型,否则代码将编译不通过: + +```cs +// create a FasterKvCache +// only set T type value +var cache = new FasterKvCache("MyTCache", + new DefaultSystemClock(), + new FasterKvCacheOptions(), + new IFasterKvCacheSerializer[] + { + new MessagePackFasterKvCacheSerializer + { + Name = "MyTCache" + } + }, + null); +``` + +### Microsoft.Extensions.DependencyInjection + +当然,我们也可以直接使用依赖注入的方式使用它,用起来也非常简单。按照通用和泛型版本的区别,我们使用不同的扩展方法即可: + +```cs +var services = new ServiceCollection(); +// use AddFasterKvCache +services.AddFasterKvCache(options => +{ + // use MessagePack serializer + options.UseMessagePackSerializer(); +}, "MyKvCache"); + +var provider = services.BuildServiceProvider(); + +// get instance do something +var cache = provider.GetService(); +``` + +泛型版本需要调用相应的`AddFasterKvCache`方法: + +```cs +var services = new ServiceCollection(); +// use AddFasterKvCache +services.AddFasterKvCache(options => +{ + // use MessagePack serializer + options.UseMessagePackSerializer(); +}, "MyKvCache"); + +var provider = services.BuildServiceProvider(); + +// get instance do something +var cache = provider.GetService>(); +``` + +## 配置 + +### FasterKvCache构造函数 + +```cs +public FasterKvCache( + string name, // 如果存在多个Cache实例,定义一个名称可以隔离序列化等配置和磁盘文件 + ISystemClock systemClock, // 当前系统时钟,new DefaultSystemClock()即可 + FasterKvCacheOptions? options, // FasterKvCache的详细配置,详情见下文 + IEnumerable? serializers, // 序列化器,可以直接使用MessagePack或SystemTextJson序列化器 + ILoggerFactory? loggerFactory) // 日志工厂 用于记录FasterKv内部的一些日志信息 +``` + +### FasterKvCacheOptions 配置项 + +对于FasterKvCache,有着和FasterKv差不多的配置项,更详细的信息大家可以看[FasterKv-Settings](https://microsoft.github.io/FASTER/docs/fasterkv-basics/#fasterkvsettings),下方是FasterKvCache的配置: + +* IndexCount:FasterKv会维护一个hash索引池,IndexCount就是这个索引池的hash槽数量,一个槽为64bit。需要配置为2的次方。如1024(2的10次方)、 2048(2的11次方)、65536(2的16次方) 、131072(2的17次方)。**默认槽数量为131072,占用1024kb的内存。** +* MemorySizeBit: FasterKv用来保存Log的内存字节数,配置为2的次方数。**默认为24,也就是2的24次方,使用16MB内存。** +* PageSizeBit:FasterKv内存页的大小,配置为2的次方数。**默认为20,也就是2的20次方,每页大小为1MB内存。** +* ReadCacheMemorySizeBit:FasterKv读缓存内存字节数,配置为2的次方数,缓存内的都是热点数据,最好设置为热点数据所占用的内存数量。**默认为20,也就是2的20次方,使用16MB内存。** +* ReadCachePageSizeBit:FasterKv读缓存内存页的大小,配置为2的次方数。**默认为20,也就是2的20次方,每页大小为1MB内存。** +* LogPath:FasterKv日志文件的目录,默认会创建两个日志文件,一个以`.log`结尾,一个以`obj.log`结尾,分别存放日志信息和Value序列化信息,**注意,不要让不同的FasterKvCache使用相同的日志文件,会出现不可预料异常**。**默认为{当前目录}/FasterKvCache/{进程Id}-HLog/{实例名称}.log**。 +* SerializerName:Value序列化器名称,需要安装序列化Nuget包,如果没有单独指定`Name`的情况下,可以使用`MessagePack`和`SystemTextJson`。**默认无需指定**。 +* ExpiryKeyScanInterval:由于FasterKv不支持过期删除功能,所以目前的实现是会定期扫描所有的key,将过期的key删除。这里配置的就是扫描间隔。**默认为5分钟**。 +* CustomStore:如果您不想使用自动生成的实例,那么可以自定义的FasterKv实例。**默认为null**。 + +所以FasterKvCache所占用的内存数量基本就是`(IndexCount*64)+(MemorySize)+ReadCacheMemorySize`,当然如果Key的数量过多,那么还有加上`OverflowBucketCount * 64`。 + +## 容量规划 + +从上面提到的内容大家可以知道,FasterKvCache所占用的内存**字节**基本就是`(IndexCount * 64)+(MemorySize) + ReadCacheMemorySize + (OverflowBucketCount * 64)`。磁盘的话就是保存了所有的数据+对象序列化的数据,由于不同的序列化协议有不同的大小,大家可以先进行测试。 + +内存数据存储到FasterKv存储引擎,每个key都会额外元数据信息,存储空间占用会有一定的放大,建议在磁盘空间选择上,留有适当余量,按实际存储需求的 1.2 - 1.5倍预估。 + +如果使用内存存储 100GB 的数据,总的访问QPS不到2W,其中80%的数据都很少访问到。那么可以使用 【32GB内存 + 128GB磁盘】 存储,节省了近 70GB 的内存存储,内存成本可以下降50%+。 + +## 性能 + +目前作者还没有时间将FasterKvCache和其它主流的缓存库进行比对,现在只对FasterKvCache、EasyCaching.FasterKv和EasyCaching.Sqlite做的比较。下面是FasterKVCache的配置,总内存占用约为**2MB**。 + +```cs +services.AddFasterKvCache(options => +{ + options.IndexCount = 1024; + options.MemorySizeBit = 20; + options.PageSizeBit = 20; + options.ReadCacheMemorySizeBit = 20; + options.ReadCachePageSizeBit = 20; + // use MessagePack serializer + options.UseMessagePackSerializer(); +}, "MyKvCache"); +``` + +由于作者笔记本性能不够,使用Sqlite无法在短期内完成100W、1W个Key的性能测试,所以我们在默认设置下将数据集大小设置为1000个Key,设置50%的热点Key。进行100%读、100%写和50%读写随机比较。 + +可以看到无论是读、写还是混合操作FasterKvCache都有着不俗的性能,在8个线程情况下,TPS达到了**惊人的1600w/s**。 + +| Provider | Type | ThreadNum | Mean(us) | Error(us) | StdDev(us) | Gen0 | Gen1 | Allocated | +| ------------- | ------ | --------- | ---------- | ---------- | ---------- | ------- | ------ | ---------- | +| fasterKvCache | Read | 8 | 59.95 | 3.854 | 2.549 | 1.5259 | 7.02 | NULL | +| fasterKvCache | Write | 8 | 63.67 | 1.032 | 0.683 | 0.7935 | 3.63 | NULL | +| fasterKvCache | Random | 4 | 64.42 | 1.392 | 0.921 | 1.709 | 8.38 | NULL | +| fasterKvCache | Read | 4 | 64.67 | 0.628 | 0.374 | 2.5635 | 11.77 | NULL | +| fasterKvCache | Random | 8 | 64.80 | 3.639 | 2.166 | 1.0986 | 5.33 | NULL | +| fasterKvCache | Write | 4 | 65.57 | 3.45 | 2.053 | 0.9766 | 4.93 | NULL | +| fasterKv | Read | 8 | 92.15 | 10.678 | 7.063 | 5.7373 | - | 26.42 KB | +| fasterKv | Write | 4 | 99.49 | 2 | 1.046 | 10.7422 | - | 49.84 KB | +| fasterKv | Write | 8 | 108.50 | 5.228 | 3.111 | 5.6152 | - | 25.93 KB | +| fasterKv | Read | 4 | 109.37 | 1.476 | 0.772 | 10.9863 | - | 50.82 KB | +| fasterKv | Random | 8 | 119.94 | 14.175 | 9.376 | 5.7373 | - | 26.18 KB | +| fasterKv | Random | 4 | 124.31 | 6.191 | 4.095 | 10.7422 | - | 50.34 KB | +| fasterKvCache | Read | 1 | 207.77 | 3.307 | 1.73 | 9.2773 | 43.48 | NULL | +| fasterKvCache | Random | 1 | 208.71 | 1.832 | 0.958 | 6.3477 | 29.8 | NULL | +| fasterKvCache | Write | 1 | 211.26 | 1.557 | 1.03 | 3.418 | 16.13 | NULL | +| fasterKv | Write | 1 | 378.60 | 17.755 | 11.744 | 42.4805 | - | 195.8 KB | +| fasterKv | Read | 1 | 404.57 | 17.477 | 11.56 | 43.457 | - | 199.7 KB | +| fasterKv | Random | 1 | 441.22 | 14.107 | 9.331 | 42.9688 | - | 197.75 KB | +| sqlite | Read | 8 | 7450.11 | 260.279 | 172.158 | 54.6875 | 7.8125 | 357.78 KB | +| sqlite | Read | 4 | 14309.94 | 289.113 | 172.047 | 109.375 | 15.625 | 718.9 KB | +| sqlite | Read | 1 | 56973.53 | 1,774.35 | 1,173.62 | 400 | 100 | 2872.18 KB | +| sqlite | Random | 8 | 475535.01 | 214,015.71 | 141,558.14 | - | - | 395.15 KB | +| sqlite | Random | 4 | 1023524.87 | 97,993.19 | 64,816.43 | - | - | 762.46 KB | +| sqlite | Write | 8 | 1153950.84 | 48,271.47 | 28,725.58 | - | - | 433.7 KB | +| sqlite | Write | 4 | 2250382.93 | 110,262.72 | 72,931.96 | - | - | 867.7 KB | +| sqlite | Write | 1 | 4200783.08 | 43,941.69 | 29,064.71 | - | - | 3462.89 KB | +| sqlite | Random | 1 | 5383716.10 | 195,085.96 | 129,037.28 | - | - | 2692.09 KB | + +## 其它 + +由于现在还只是1.0.0-rc1版本,还有很多特性没有实现。可能有一些BUG还存在,欢迎大家试用和反馈问题。 diff --git a/benchmark/FasterKvCache.Benchmark/FasterKvCache.Benchmark.csproj b/benchmark/FasterKvCache.Benchmark/FasterKvCache.Benchmark.csproj new file mode 100644 index 0000000..cc16331 --- /dev/null +++ b/benchmark/FasterKvCache.Benchmark/FasterKvCache.Benchmark.csproj @@ -0,0 +1,20 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + + + + + + + diff --git a/benchmark/FasterKvCache.Benchmark/Program.cs b/benchmark/FasterKvCache.Benchmark/Program.cs new file mode 100644 index 0000000..57cf66a --- /dev/null +++ b/benchmark/FasterKvCache.Benchmark/Program.cs @@ -0,0 +1,128 @@ +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; +using BenchmarkDotNet.Order; +using FasterKv.Cache.Core; +using FasterKv.Cache.Core.Configurations; +using FasterKv.Cache.MessagePack; +using Microsoft.Extensions.DependencyInjection; + +BenchmarkDotNet.Running.BenchmarkRunner.Run(); + +public enum TestType +{ + Read, + Write, + Random +} + +[GcForce] +[Orderer(SummaryOrderPolicy.FastestToSlowest)] +[SimpleJob(RuntimeMoniker.Net60, launchCount: 1, warmupCount: 5, targetCount: 10)] +[MemoryDiagnoser] +#nullable disable +public class FasterKvBenchmark +{ + private const long Count = 1000; + private static readonly Random _random = new Random(1024); + private FasterKvCache _provider; + private static readonly TimeSpan _default = TimeSpan.FromSeconds(30); + + + [Params(TestType.Read, TestType.Write, TestType.Random)] + public TestType Type { get; set; } + + [Params(1,4,8)] + public int ThreadCount { get; set; } + + private static readonly string[] HotKeys = Enumerable.Range(0, (int)(Count * 0.5)) + .Select(i => $"cache_{_random.Next(0, (int) Count)}") + .ToArray(); + + [GlobalSetup] + public void Setup() + { + var services = new ServiceCollection(); + services.AddFasterKvCache(options => + { + options.IndexCount = 1024; + options.MemorySizeBit = 20; + options.PageSizeBit = 20; + options.ReadCacheMemorySizeBit = 20; + options.ReadCachePageSizeBit = 20; + // use MessagePack serializer + options.UseMessagePackSerializer(); + }, "MyKvCache"); + IServiceProvider serviceProvider = services.BuildServiceProvider(); + _provider = serviceProvider.GetService>()!; + + switch (Type) + { + case TestType.Write: + break; + case TestType.Read: + case TestType.Random: + for (int i = 0; i < Count; i++) + { + _provider!.Set($"cache_{i}", "cache", _default); + } + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + [Benchmark] + public async Task Full() + { + var tasks = new Task[ThreadCount]; + var threadOpCount = (int)(HotKeys.Length / ThreadCount); + for (int i = 0; i < ThreadCount; i++) + { + int i1 = i; + tasks[i] = Task.Run(() => + { + var j = i1 * threadOpCount; + switch (Type) + { + case TestType.Read: + for (; j < threadOpCount; j++) + { + _provider.Get(HotKeys[j]); + } + + break; + case TestType.Write: + for (; j < threadOpCount; j++) + { + _provider.Set(HotKeys[j], "cache", _default); + } + + break; + case TestType.Random: + for (; j < threadOpCount; j++) + { + if (j % 2 == 0) + { + _provider.Get(HotKeys[j]); + } + else + { + _provider.Set(HotKeys[j], "cache", _default); + } + } + + break; + } + }); + } + + await Task.WhenAll(tasks); + } + + + [GlobalCleanup] + public void Cleanup() + { + _provider.Dispose(); + } +} \ No newline at end of file diff --git a/docs/assets/arch.png b/docs/assets/arch.png new file mode 100644 index 0000000000000000000000000000000000000000..3883ecfb72d5b9a2be63852130a999c4e6c859b6 GIT binary patch literal 96519 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 + + + Exe + net6.0 + enable + enable + + + + + + + + diff --git a/sample/FasterKvCache.Sample.ConsoleApp/ObjectFasterKvCache.cs b/sample/FasterKvCache.Sample.ConsoleApp/ObjectFasterKvCache.cs new file mode 100644 index 0000000..4ef34bd --- /dev/null +++ b/sample/FasterKvCache.Sample.ConsoleApp/ObjectFasterKvCache.cs @@ -0,0 +1,52 @@ +using FasterKv.Cache.Core; +using FasterKv.Cache.Core.Configurations; +using FasterKv.Cache.MessagePack; + +namespace FasterKvCache.Sample.ConsoleApp; + +public class ObjectFasterKvCache +{ + public async Task Run() + { + // create a FasterKvCache + var cache = new FasterKv.Cache.Core.FasterKvCache("MyCache", + new DefaultSystemClock(), + new FasterKvCacheOptions(), + new IFasterKvCacheSerializer[] + { + new MessagePackFasterKvCacheSerializer + { + Name = "MyCache" + } + }, + null); + + var key = Guid.NewGuid().ToString("N"); + + // sync + // set key and value with expiry time + cache.Set(key, "my cache sync", TimeSpan.FromMinutes(5)); + + // get + var result = cache.Get(key); + Console.WriteLine(result); + + // delete + cache.Delete(key); + + // async + // set + await cache.SetAsync(key, "my cache async"); + + // get + result = await cache.GetAsync(key); + Console.WriteLine(result); + + // delete + await cache.DeleteAsync(key); + + // set other type object + cache.Set(key, new DateTime(2022,2,22)); + Console.WriteLine(cache.Get(key)); + } +} \ No newline at end of file diff --git a/sample/FasterKvCache.Sample.ConsoleApp/Program.cs b/sample/FasterKvCache.Sample.ConsoleApp/Program.cs new file mode 100644 index 0000000..76f5844 --- /dev/null +++ b/sample/FasterKvCache.Sample.ConsoleApp/Program.cs @@ -0,0 +1,4 @@ +using FasterKvCache.Sample.ConsoleApp; + +_ = new ObjectFasterKvCache().Run(); +_ = new TFasterKvCache().Run(); diff --git a/sample/FasterKvCache.Sample.ConsoleApp/TFasterKvCache.cs b/sample/FasterKvCache.Sample.ConsoleApp/TFasterKvCache.cs new file mode 100644 index 0000000..a30256b --- /dev/null +++ b/sample/FasterKvCache.Sample.ConsoleApp/TFasterKvCache.cs @@ -0,0 +1,49 @@ +using FasterKv.Cache.Core; +using FasterKv.Cache.Core.Configurations; +using FasterKv.Cache.MessagePack; + +namespace FasterKvCache.Sample.ConsoleApp; + +public class TFasterKvCache +{ + public async Task Run() + { + // create a FasterKvCache + var cache = new FasterKvCache("MyTCache", + new DefaultSystemClock(), + new FasterKvCacheOptions(), + new IFasterKvCacheSerializer[] + { + new MessagePackFasterKvCacheSerializer + { + Name = "MyTCache" + } + }, + null); + + var key = Guid.NewGuid().ToString("N"); + + // sync + // set key and value with expiry time + cache.Set(key, "my cache sync", TimeSpan.FromMinutes(5)); + + // get + var result = cache.Get(key); + Console.WriteLine(result); + + // delete + cache.Delete(key); + + // async + // set + await cache.SetAsync(key, "my cache async"); + + + // get + result = await cache.GetAsync(key); + Console.WriteLine(result); + + // delete + await cache.DeleteAsync(key); + } +} \ No newline at end of file diff --git a/src/FasterKv.Cache.Core/Configurations/FasterKvCacheOptions.cs b/src/FasterKv.Cache.Core/Configurations/FasterKvCacheOptions.cs index 7ed9f89..71171ba 100644 --- a/src/FasterKv.Cache.Core/Configurations/FasterKvCacheOptions.cs +++ b/src/FasterKv.Cache.Core/Configurations/FasterKvCacheOptions.cs @@ -40,7 +40,7 @@ public class FasterKvCacheOptions /// /// FasterKv read cache page size /// - /// Default: 16MB + /// Default: 1MB public int ReadCachePageSizeBit { get; set; } = 20; /// diff --git a/tests/FasterKv.Cache.Core.Tests/DependencyInjection/FasterKvCacheDITest.cs b/tests/FasterKv.Cache.Core.Tests/DependencyInjection/FasterKvCacheDITest.cs index 7fd9055..95d89cf 100644 --- a/tests/FasterKv.Cache.Core.Tests/DependencyInjection/FasterKvCacheDITest.cs +++ b/tests/FasterKv.Cache.Core.Tests/DependencyInjection/FasterKvCacheDITest.cs @@ -14,26 +14,24 @@ public void Use_MessagePackSerializer_Create_FasterKvCache_Should_Success() var services = new ServiceCollection(); services.AddFasterKvCache(options => { + // use MessagePack serializer options.UseMessagePackSerializer(); - },"MyKvCache"); + }, "MyKvCache"); var provider = services.BuildServiceProvider(); var cache = provider.GetService(); Assert.NotNull(cache); - - cache!.Set("abc","abc"); + + cache!.Set("abc", "abc"); var result = cache.Get("abc"); Assert.Equal("abc", result); } - + [Fact] public void Use_MessagePackSerializer_Create_FasterKvCacheTValue_Should_Success() { var services = new ServiceCollection(); - services.AddFasterKvCache(options => - { - options.UseMessagePackSerializer(); - },"MyKvCache"); + services.AddFasterKvCache(options => { options.UseMessagePackSerializer(); }, "MyKvCache"); var provider = services.BuildServiceProvider(); var cache = provider.GetService>(); @@ -44,35 +42,31 @@ public void Use_MessagePackSerializer_Create_FasterKvCacheTValue_Should_Success( One = "1024", Two = 1024 }; - cache!.Set("abc",data); + cache!.Set("abc", data); var result = cache.Get("abc"); Assert.Equal(data, result); - } [Fact] + } + + [Fact] public void Use_SystemTextJson_Create_FasterKvCache_Should_Success() { var services = new ServiceCollection(); - services.AddFasterKvCache(options => - { - options.UseSystemTextJsonSerializer(); - },"MyKvCache"); + services.AddFasterKvCache(options => { options.UseSystemTextJsonSerializer(); }, "MyKvCache"); var provider = services.BuildServiceProvider(); var cache = provider.GetService(); Assert.NotNull(cache); - - cache!.Set("abc","abc"); + + cache!.Set("abc", "abc"); var result = cache.Get("abc"); Assert.Equal("abc", result); } - + [Fact] public void Use_SystemTextJson_Create_FasterKvCacheTValue_Should_Success() { var services = new ServiceCollection(); - services.AddFasterKvCache(options => - { - options.UseSystemTextJsonSerializer(); - },"MyKvCache"); + services.AddFasterKvCache(options => { options.UseSystemTextJsonSerializer(); }, "MyKvCache"); var provider = services.BuildServiceProvider(); var cache = provider.GetService>(); @@ -83,7 +77,7 @@ public void Use_SystemTextJson_Create_FasterKvCacheTValue_Should_Success() One = "1024", Two = 1024 }; - cache!.Set("abc",data); + cache!.Set("abc", data); var result = cache.Get("abc"); Assert.Equal(data, result); }