Clojure China

Memory usage of `memoize` function?

#1

Since this function is always storing data, will it eat up all the memories?

(defn memoize
  "Returns a memoized version of a referentially transparent function. The
  memoized version of the function keeps a cache of the mapping from arguments
  to results and, when calls with the same arguments are repeated often, has
  higher performance at the expense of higher memory use."
  {:added "1.0"
   :static true}
  [f]
  (let [mem (atom {})]
    (fn [& args]
      (if-let [e (find @mem args)]
        (val e)
        (let [ret (apply f args)]
          (swap! mem assoc args ret)
          ret)))))
#2

memoize函数将值记录在内存中,不需要重复计算,有什么需要注意的?

#3

如果函数被调用的次数非常费多, 储存的计算结果也会越来越多, 占用的内存按说是要增加. 另外存储的内容多的时候, 对比 args 的开销也会变大, 最终程序越来越慢, 我想知道这个临界点是在哪?

#4

记忆功能说白了就是缓存功能。启用缓存肯定会有一个临界值,但是这和实际项目各种设定相关,很不确定;再说你的临界点的衡量单位是什么呢?记录的条数,还是字节数?很难给出确切的答案。

说到memorize,Groovy语言中提供了memoizeAtMost(), memoizeAtLeast(), memoizeBetween()等记忆方法,而clojure的contrib lib core.memoize也提供了各种缓存策略的方法。

从实现上看,原生的memoize()方法估计会一直耗完内存。

#5

有个库来帮忙处理下还挺好的, 我知道都不知道有这些个实现, README 太简单了.
可惜我现在的代码还有用 shallow equal 来优化, 这都用不上…

#6

两篇关于memorize文章,exploring clojure emoizationmemoize done right,第二篇有深度。

1赞
#7

看实现是会耗尽内存的;函数的文档也说明了是空间换时间,应根据具体的需求决定该方法的应用,如果重复调用
某计算函数的情况较多,该memozie就能大显神威了

#8

手动搞了一个, 结果 get 函数调用慢得要死.