2016-08-06 2 views
2

ここにこのサイトの名前のついた質問があります。ClojureコアキャッシュStackoverflow

なぜこのコードはClojureでStackOverflow例外をスローしますか?

(require [clojure.core.cache :as cache]) 

(def C (atom (cache/fifo-cache-factory {} :threshold 1E7))) 

(doseq [i (range 1 1E6)] 
    (swap! C cache/miss i i)) 

私は次のようになります。私は自分のコードでconcat操作をしませんでした。 これは非常に再現性があります。私は

Caused by: java.lang.StackOverflowError 
    at clojure.lang.RT.seq(RT.java:507) 
    at clojure.core$seq__4128.invoke(core.clj:137) 
    at clojure.core$concat$fn__4215.invoke(core.clj:691) 
    at clojure.lang.LazySeq.sval(LazySeq.java:40) 
    at clojure.lang.LazySeq.seq(LazySeq.java:49) 
    at clojure.lang.RT.seq(RT.java:507) 
    at clojure.core$seq__4128.invoke(core.clj:137) 
    at clojure.core$concat$fn__4215.invoke(core.clj:691) 
    at clojure.lang.LazySeq.sval(LazySeq.java:40) 
    at clojure.lang.LazySeq.seq(LazySeq.java:49) 
    at clojure.lang.RT.seq(RT.java:507) 

........... 
........... 
    at clojure.core$concat$fn__4215.invoke(core.clj:691) 
    at clojure.lang.LazySeq.sval(LazySeq.java:40) 
    at clojure.lang.LazySeq.seq(LazySeq.java:49) 
    at clojure.lang.RT.seq(RT.java:507) 
    at clojure.core$seq__4128.invoke(core.clj:137) 
    at clojure.core$concat$fn__4215.invoke(core.clj:691) 
    at clojure.lang.LazySeq.sval(LazySeq.java:40) 
    at clojure.lang.LazySeq.seq(LazySeq.java:49) 
    at clojure.lang.RT.seq(RT.java:507) 
    at clojure.core$seq__4128.invoke(core.clj:137) 
    at clojure.core$concat$fn__4215.invoke(core.clj:691) 
    at clojure.lang.LazySeq.sval(LazySeq.java:40) 
    at clojure.lang.LazySeq.seq(LazySeq.java:49) 
    at clojure.lang.RT.seq(RT.java:507) 
    at clojure.core$seq__4128.invoke(core.clj:137) 
    at clojure.core$concat$fn__4215.invoke(core.clj:691) 
    at clojure.lang.LazySeq.sval(LazySeq.java:40) 
    at clojure.lang.LazySeq.seq(LazySeq.java:49) 
    at clojure.lang.RT.seq(RT.java:507) 
    at clojure.core$seq__4128.invoke(core.clj:137) 
    at clojure.core$concat$fn__4215.invoke(core.clj:691) 
    at clojure.lang.LazySeq.sval(LazySeq.java:40) 

答えて

4

core.cacheは古典的な怠惰なシーケンスの間違いをしているのJava 8でのClojure 1.7を使用しています:多くの怠惰な-シーケンスを連結一緒に、これまでの結果を見ず。 FIFOCacheにはqueue of past missesが格納され、キャッシュ内の領域が不足すると、そのキュー内の最も古いアイテムが削除されます。しかし、これに実際のキュー構造を使用する代わりに、レイジーシーケンスを使用して末尾に連結します(結果は、Recursive function causing a stack overflowなど)。

これはcore.cacheのバグです。 its JIRAに対して問題を提出したり、そのような大きなFIFOキャッシュを使用しないで回避することができます。恐らく数千程度のサイズまで動作します。

+0

申し訳ありません。この問題の修正に関心のある人は、https://github.com/ravigit/core.cacheにアクセスしてください。変更はhttps://github.com/ravigit/core.cache/commit/c8a60dda1d3ff74b7f91eacf97ebcaa1eadb2c30?diff=splitです。自己責任で使用してください! – Ravi

+1

'' prune-queue'は、 'remove'を呼び出してキューを遅延シーケンスに変換するので、修正する必要があります。 – amalloy

+0

良い点。すぐに修正を提供します。 – Ravi