Clojure - 在磁盘上记忆

Clojure - memoize on disk

我想提高 returns 调整图像大小的功能的性能。请求的图像大小不应有太大差异(取决于设备),因此以某种方式缓存结果是有意义的。

我当然可以将它存储在磁盘上,并检查是否存在调整大小的图像,并确保如果原始图像被删除,调整大小的版本也...

或者,我可以使用记忆函数。但是由于结果可能非常大(我认为一个图像大约 5 - 10 MB),将它们存储在内存中没有意义(几十 GB 的图像及其修改版本会很快填满内存).

那么,有没有一种方法可以像常规 Clojure defmemo 一样使用记忆函数,但它是由本地磁盘中的文件夹而不是内存支持的?然后我可以使用 ttl 策略来确保图像不会长时间不同步。

类似于 crache,但由文件系统支持?

您需要的听起来像是 Datomic 的完美用法。它很容易从 Clojure 中使用,非常高效,并且像任何好的 DB 一样,它在内存中有一个最近最少使用 (LRU) 缓存。它还可以使用各种支持数据库作为基础,从严格的内存(最适合测试和实验)到 Postgres、Redis、DynamoDB、Riak 等。还有一个 "dev" 模式使用本地所有存储的文件。

在此处查看所有详细信息:

有一个标准版本,带有适合大多数用途的免费永久许可证。对于高级功能,可以使用付费版本。

为什么不从 clojure.core.cache 实现 TTL 缓存,用您需要的功能包装它?您的键可以是任何标识您调整大小的图像,值将是它在磁盘上的位置。然后你可以实现某种获取或设置!函数,将它传递给当图像不存在时将被调用以生成图像的函数。 例如

(def Cache (atom (cache/ttl-cache-factory {} :ttl 20000)))

(defn get-or-update!
  "wraps the recommended has-hit-get pattern
   https://github.com/clojure/core.cache/wiki/Using"
  [key fn]
  (if (cache/has? @Cache key)
    (get (swap! Cache #(cache/hit % key)) key)
    (get (swap! Cache #(cache/miss % key (fn))) key)))

别想太多了。您的文件系统作为缓存是正确的想法。如果一个文件变得流行并且该文件被大量访问,那么您的操作系统将确保它在 RAM 中。这与许多数据库使用的策略相同。例如 Elasticsearch 要求您保留足够的 RAM 以在 RAM 中保存 Lucene 索引文件。

也不要修改您的文件!以功能方式进行:将它们视为不可变数据。您的输入文件不应更改。如果是,那么它就是一个新文件。硬盘 space 非常便宜。不要害怕周围有很多文件。如果必须,您可以执行垃圾收集,在一段时间后删除 old/flagged 个文件。

要查看文件是否在缓存中,您只需检查文件是否存在。如果不是:你写一次。

总结一下:

  • 让您的 O/S 处理缓存
  • 不要编辑您的文件。将它们视为不可变数据。写一次
  • 您的 O/S 将释放未使用文件的 RAM。硬盘space超级便宜