{"id":13799335,"url":"https://github.com/jitbit/FastCache","last_synced_at":"2025-05-13T08:31:03.403Z","repository":{"id":144655784,"uuid":"538599750","full_name":"jitbit/FastCache","owner":"jitbit","description":"7x-10x faster alternative to MemoryCache. A high-performance, lighweight (8KB dll) and thread-safe memory cache for .NET.","archived":false,"fork":false,"pushed_at":"2025-05-02T23:23:12.000Z","size":99,"stargazers_count":162,"open_issues_count":0,"forks_count":16,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-11T13:52:17.819Z","etag":null,"topics":["cache","dotnet","performance"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jitbit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-19T16:41:43.000Z","updated_at":"2025-05-08T17:55:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"99fc2448-34f8-4303-a497-82268ea3ff8e","html_url":"https://github.com/jitbit/FastCache","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jitbit%2FFastCache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jitbit%2FFastCache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jitbit%2FFastCache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jitbit%2FFastCache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jitbit","download_url":"https://codeload.github.com/jitbit/FastCache/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253576227,"owners_count":21930165,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","dotnet","performance"],"created_at":"2024-08-04T00:01:01.651Z","updated_at":"2025-05-13T08:31:03.397Z","avatar_url":"https://github.com/jitbit.png","language":"C#","readme":"# FastCache\n\n7x-10x faster alternative to MemoryCache. A high-performance, lighweight (8KB dll) and [thread-safe](Atomic.md) memory cache for .NET Core (.NET 6 and later)\n\n[![NuGet version](https://badge.fury.io/nu/Jitbit.FastCache.svg)](https://badge.fury.io/nu/Jitbit.FastCache)\n[![.NET](https://github.com/jitbit/FastCache/actions/workflows/dotnet.yml/badge.svg)](https://github.com/jitbit/FastCache/actions/workflows/dotnet.yml)\n\n## TL;DR\n\nBasically it's just a `ConcurrentDictionary` with expiration.\n\n## Benchmarks\n\nWindows:\n\n|               Method |      Mean |     Error |   StdDev |   Gen0 | Allocated |\n|--------------------- |----------:|----------:|---------:|-------:|----------:|\n|     DictionaryLookup |  65.38 ns |  1.594 ns | 0.087 ns |      - |         - |\n|    FastCacheLookup   |  67.15 ns |  2.582 ns | 0.142 ns |      - |         - |\n|    MemoryCacheLookup | 426.60 ns | 60.162 ns | 3.298 ns | 0.0200 |     128 B |\n|    FastCacheGetOrAdd |  80.44 ns |  1.170 ns | 0.064 ns |      - |         - |\n|  MemoryCacheGetOrAdd | 826.85 ns | 36.609 ns | 2.007 ns | 0.1879 |    1184 B |\n|   FastCacheAddRemove |  99.97 ns | 12.040 ns | 0.660 ns | 0.0063 |      80 B |\n| MemoryCacheAddRemove | 710.70 ns | 32.415 ns | 1.777 ns | 0.0515 |     328 B |\n\nLinux (Ubuntu, Docker):\n\n|               Method |        Mean |      Error |    StdDev |   Gen0 | Allocated |\n|--------------------- |------------:|-----------:|----------:|-------:|----------:|\n|      FastCacheLookup |    94.97 ns |   3.250 ns |  0.178 ns |      - |         - |\n|    MemoryCacheLookup | 1,051.69 ns |  64.904 ns |  3.558 ns | 0.0191 |     128 B |\n|   FastCacheAddRemove |   148.32 ns |  25.766 ns |  1.412 ns | 0.0076 |      80 B |\n| MemoryCacheAddRemove | 1,120.75 ns | 767.666 ns | 42.078 ns | 0.0515 |     328 B |\n\n## How is FastCache better\n\nCompared to `System.Runtime.Caching.MemoryCache` and `Microsoft.Extensions.Caching.MemoryCache` FastCache is\n\n* 7X faster reads (11X under Linux!)\n* 10x faster writes\n* Thread safe and [atomic](https://www.jitbit.com/alexblog/fast-memory-cache/#perf)\n* Generic (strongly typed keys and values) to avoid boxing/unboxing primitive types\n* MemoryCache uses string keys only, so it allocates strings for keying\n* MemoryCache comes with performance counters that can't be turned off\n* MemoryCache uses heuristic and black magic to evict keys under memory pressure\n* MemoryCache uses more memory, can crash during a key scan\n\n## Usage\n\nInstall via nuget\n\n```\nInstall-Package Jitbit.FastCache\n```\n\nThen use\n\n```csharp\nvar cache = new FastCache\u003cstring, int\u003e();\n\ncache.AddOrUpdate(\n\tkey: \"answer\",\n\tvalue: 42,\n\tttl: TimeSpan.FromMinutes(1));\n\ncache.TryGet(\"answer\", out int value); //value is \"42\"\n\n//factory pattern! calls the expensive factory only if not cached yet\ncache.GetOrAdd(\n\tkey: \"answer\",\n\tvalueFactory: k =\u003e 42,\n\tttl: TimeSpan.FromMilliseconds(100));\n\n//handy overload to prevent captures/closures allocation\ncache.GetOrAdd(\n\tkey: \"answer\",\n\tvalueFactory: (k, arg) =\u003e 42 + arg.Length,\n\tttl: TimeSpan.FromMilliseconds(100),\n\tfactoryArgument: \"some state data\");\n\n```\n\n## Tradeoffs\n\nFastCache uses `Environment.TickCount` to monitor items' TTL. `Environment.TickCount` is 104x times faster than using `DateTime.Now` and 26x times faster than `DateTime.UtcNow`.\n\n~~But `Environment.TickCount` is limited to `Int32`. Which means it resets to `int.MinValue` once overflowed. This is not a problem, we do have a workaround for that. However this means you cannot cache stuff for more than 25 days (2.4 billion milliseconds).~~\n\nThe above is no longer valid, we have switched to .NET 6 targeting and now use `TickCount64` which is free of this problem.\n\nAnother tradeoff: MemoryCache watches memory usage, and evicts items once it senses memory pressure. **FastCache does not do any of that** it is up to you to keep your caches reasonably sized. After all, it's just a dictionary.\n","funding_links":[],"categories":["Caching"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjitbit%2FFastCache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjitbit%2FFastCache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjitbit%2FFastCache/lists"}