{"id":17299885,"url":"https://github.com/twmb/go-cache","last_synced_at":"2025-04-13T05:39:32.008Z","repository":{"id":70205861,"uuid":"518347700","full_name":"twmb/go-cache","owner":"twmb","description":" A concurrency safe, mostly lock-free, singleflight request collapsing generic cache with support for stale values.","archived":false,"fork":false,"pushed_at":"2024-02-07T00:51:07.000Z","size":38,"stargazers_count":12,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-26T22:13:38.529Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"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/twmb.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-07-27T07:06:53.000Z","updated_at":"2025-03-20T11:57:29.000Z","dependencies_parsed_at":"2024-02-07T01:52:05.569Z","dependency_job_id":null,"html_url":"https://github.com/twmb/go-cache","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twmb%2Fgo-cache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twmb%2Fgo-cache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twmb%2Fgo-cache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twmb%2Fgo-cache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/twmb","download_url":"https://codeload.github.com/twmb/go-cache/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248670506,"owners_count":21142897,"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":[],"created_at":"2024-10-15T11:24:21.741Z","updated_at":"2025-04-13T05:39:31.746Z","avatar_url":"https://github.com/twmb.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"cache\n=====\n\nPackage cache provides a concurrency safe, mostly lock-free, singleflight\nrequest collapsing generic cache with support for stale values.\n\nThe guts of this package are similar to `sync.Map`, with minor differences in\nwhen the internal locked write-map is promoted an atomic read-only map, and\nmajor differences to support singleflight request collapsing.\n\nFunctions in this API that return a `KeyState` return the state last, rather\nthan the error last: the value and error are cached as a single internal unit\nand can be thought of as a single value.\n\nThe following logical mapping can be done from `sync.Map` to `cache.Cache`\nfunctions:\n\n```go\n  sync.Map.CompareAndDelete == cache.Cache.CompareAndDelete\n  sync.Map.CompareAndSwap   == cache.Cache.CompareAndSwap\n  sync.Map.Delete           == (no equivalent -- we just provide LoadAndDelete)\n  sync.Map.Load             == cache.Cache.TryGet\n  sync.Map.LoadAndDelete    == cache.Cache.Delete\n  sync.Map.LoadOrStore      == cache.Cache.Get\n  sync.Map.Range            == cache.Cache.Range\n  sync.Map.Store            == cache.Cache.Set\n  sync.Map.Swap             == cache.Cache.Swap\n```\n\n\nThe cache has the concept of expiring values with max ages. As well, a stale\nvalue can be kept and returned from `Get` during a refresh / if a refresh\nfails. Keys can be manually expired with `Expire`. Internally expired values or\nerrors can be occasionally cleaned with `Clean`.\n\nOut of an abundance of paranoia that this code is correct, there are unit tests\nto hit 97% coverage of the `cache.Cache` type. As well, all tests against\n`sync.Map` are copied into this library and used against `cache.Cache`.\n\nThis package also provides a cached `Item` and a `Set`. `Item` can be used to\npopulate an expensive value once and expire or replace it when needed, similar\nto a singleton. `Set` can be used as a standard set for when key values are\nexpensive. Functions that do not make sense on either of these types are not\nprovided (e.g., `CompareAndSwap` for a `Set`).\n\nDocumentation\n-------------\n\n[![godev](https://img.shields.io/static/v1?label=godev\u0026message=reference\u0026color=00add8)][godev]\n\n[godev]: https://pkg.go.dev/github.com/twmb/go-cache/cache\n\nBenchmarking\n------------\n\nSome of the APIs are actually faster or more memory efficient than `sync.Map`\nbecause of generics. Some are slower and require more allocs because of the\nrequest collapsing aspect. Some benchmarks below show more CPU, but this is due\nto a few slight changes in how the write (dirty) map is internally promoted to\nthe read map.\n\nThe benchmarks are from the stdlib using a key and value of type int:\n\n```\nname                          old time/op    new time/op    delta\nLoadMostlyHits                  12.8ns ±44%    14.0ns ±50%      ~     (p=0.393 n=10+10)\nLoadMostlyMisses                10.7ns ±53%     4.6ns ±47%   -57.31%  (p=0.000 n=10+10)\nLoadOrStoreBalanced              351ns ± 3%     705ns ±27%  +100.68%  (p=0.000 n=8+10)\nLoadOrStoreUnique                663ns ±13%    1296ns ±31%   +95.53%  (p=0.000 n=10+10)\nLoadOrStoreCollision            9.71ns ±60%   29.26ns ±46%  +201.44%  (p=0.000 n=10+10)\nLoadAndDeleteBalanced           11.2ns ±42%     7.1ns ±48%   -36.06%  (p=0.035 n=10+10)\nLoadAndDeleteUnique             9.19ns ±62%    4.17ns ±47%   -54.59%  (p=0.001 n=10+10)\nLoadAndDeleteCollision          10.9ns ±41%    14.3ns ±35%   +31.18%  (p=0.023 n=10+10)\nRange                           3.73µs ±48%    5.40µs ±45%      ~     (p=0.063 n=10+10)\nAdversarialAlloc                 298ns ±22%     259ns ±21%      ~     (p=0.063 n=10+10)\nAdversarialDelete               83.7ns ±14%   105.6ns ±20%      ~     (p=0.052 n=10+10)\nDeleteCollision                 6.87ns ±71%   4.86ns ±100%      ~     (p=0.424 n=10+10)\nSwapCollision                    201ns ±26%     266ns ±31%      ~     (p=0.143 n=10+10)\nSwapMostlyHits                  40.3ns ±42%    59.7ns ±51%      ~     (p=0.143 n=10+10)\nSwapMostlyMisses                 662ns ±18%     607ns ±24%    -8.19%  (p=0.023 n=10+10)\nCompareAndSwapCollision         33.4ns ±41%    24.9ns ±65%   -25.44%  (p=0.023 n=10+10)\nCompareAndSwapNoExistingKey     10.3ns ±46%     2.0ns ±53%   -80.15%  (p=0.000 n=10+10)\nCompareAndSwapValueNotEqual     9.64ns ±51%    6.02ns ±95%   -37.49%  (p=0.019 n=10+10)\nCompareAndSwapMostlyHits        46.9ns ±39%    56.8ns ±47%      ~     (p=0.143 n=10+10)\nCompareAndSwapMostlyMisses      22.9ns ±39%    13.4ns ±48%   -41.48%  (p=0.023 n=10+10)\nCompareAndDeleteCollision       28.1ns ±47%    18.3ns ±37%   -34.88%  (p=0.019 n=10+10)\nCompareAndDeleteMostlyHits      64.0ns ±38%    63.9ns ±52%      ~     (p=0.165 n=10+10)\nCompareAndDeleteMostlyMisses    18.3ns ±37%     8.7ns ±53%   -52.65%  (p=0.023 n=10+10)\n\nname                          old alloc/op   new alloc/op   delta\nLoadMostlyHits                   6.00B ± 0%     0.00B       -100.00%  (p=0.000 n=10+10)\nLoadMostlyMisses                 6.00B ± 0%     0.00B       -100.00%  (p=0.000 n=10+10)\nLoadOrStoreBalanced              74.7B ±16%    195.3B ± 1%  +161.45%  (p=0.000 n=10+10)\nLoadOrStoreUnique                 159B ± 7%      330B ± 7%  +107.15%  (p=0.000 n=9+10)\nLoadOrStoreCollision             0.00B         32.00B ± 0%     +Inf%  (p=0.000 n=10+10)\nLoadAndDeleteBalanced            4.00B ± 0%     0.00B       -100.00%  (p=0.000 n=10+10)\nLoadAndDeleteUnique              8.00B ± 0%     0.00B       -100.00%  (p=0.000 n=10+10)\nLoadAndDeleteCollision           1.00B ± 0%     1.00B ± 0%      ~     (all equal)\nRange                            16.0B ± 0%      0.0B       -100.00%  (p=0.000 n=10+10)\nAdversarialAlloc                 53.4B ± 3%     64.8B ± 3%   +21.35%  (p=0.000 n=10+10)\nAdversarialDelete                22.6B ±12%     39.0B ± 0%   +72.57%  (p=0.000 n=10+10)\nDeleteCollision                  0.00B          0.00B           ~     (all equal)\nSwapCollision                    16.0B ± 0%     80.0B ± 0%  +400.00%  (p=0.000 n=10+10)\nSwapMostlyHits                   28.0B ± 0%     86.0B ± 0%  +207.14%  (p=0.000 n=10+10)\nSwapMostlyMisses                  124B ± 0%      136B ± 1%    +9.71%  (p=0.000 n=10+10)\nCompareAndSwapCollision          7.60B ± 8%    21.70B ±17%  +185.53%  (p=0.000 n=10+10)\nCompareAndSwapNoExistingKey      8.00B ± 0%     0.00B       -100.00%  (p=0.000 n=10+10)\nCompareAndSwapValueNotEqual      0.00B          0.00B           ~     (all equal)\nCompareAndSwapMostlyHits         33.0B ± 0%     91.0B ± 0%  +175.76%  (p=0.000 n=10+10)\nCompareAndSwapMostlyMisses       23.0B ± 0%     16.0B ± 0%   -30.43%  (p=0.000 n=10+10)\nCompareAndDeleteCollision        0.00B          2.00B ± 0%     +Inf%  (p=0.000 n=10+8)\nCompareAndDeleteMostlyHits       39.0B ± 0%     90.6B ± 1%  +132.31%  (p=0.000 n=10+10)\nCompareAndDeleteMostlyMisses     16.0B ± 0%      8.0B ± 0%   -50.00%  (p=0.002 n=8+10)\n\nname                          old allocs/op  new allocs/op  delta\nLoadMostlyHits                    0.00           0.00           ~     (all equal)\nLoadMostlyMisses                  0.00           0.00           ~     (all equal)\nLoadOrStoreBalanced               2.00 ± 0%      3.00 ± 0%   +50.00%  (p=0.000 n=10+10)\nLoadOrStoreUnique                 4.00 ± 0%      5.00 ± 0%   +25.00%  (p=0.000 n=10+10)\nLoadOrStoreCollision              0.00           1.00 ± 0%     +Inf%  (p=0.000 n=10+10)\nLoadAndDeleteBalanced             0.00           0.00           ~     (all equal)\nLoadAndDeleteUnique              0.60 ±100%      0.00       -100.00%  (p=0.011 n=10+10)\nLoadAndDeleteCollision            0.00           0.00           ~     (all equal)\nRange                             1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)\nAdversarialAlloc                  1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)\nAdversarialDelete                 1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)\nDeleteCollision                   0.00           0.00           ~     (all equal)\nSwapCollision                     1.00 ± 0%      1.00 ± 0%      ~     (all equal)\nSwapMostlyHits                    2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)\nSwapMostlyMisses                  6.00 ± 0%      4.00 ± 0%   -33.33%  (p=0.000 n=10+10)\nCompareAndSwapCollision           0.00           0.00           ~     (all equal)\nCompareAndSwapNoExistingKey      0.50 ±100%      0.00       -100.00%  (p=0.033 n=10+10)\nCompareAndSwapValueNotEqual       0.00           0.00           ~     (all equal)\nCompareAndSwapMostlyHits          3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=10+10)\nCompareAndSwapMostlyMisses        2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)\nCompareAndDeleteCollision         0.00           0.00           ~     (all equal)\nCompareAndDeleteMostlyHits        3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=10+10)\nCompareAndDeleteMostlyMisses      1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwmb%2Fgo-cache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftwmb%2Fgo-cache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwmb%2Fgo-cache/lists"}