Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

CCACHE-23: Fixed bug where LRU and LU caches were evicting before thr…

…eshold
  • Loading branch information...
commit 1a7aaad446159f35dd0cc4a4f7c7d70fe4ababe0 1 parent 536c4bd
@fogus fogus authored
View
3  .gitignore
@@ -1 +1,4 @@
target
+.lein*
+lib
+multi-lib
View
2  pom.xml
@@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core.cache</artifactId>
- <version>0.7.0-SNAPSHOT</version>
+ <version>0.6.1-SNAPSHOT</version>
<name>${artifactId}</name>
<description>A cache library for Clojure</description>
<packaging>jar</packaging>
View
14 project.clj
@@ -0,0 +1,14 @@
+(defproject core.cache "0.7.0-SNAPSHOT"
+ :description "Cache library for Clojure."
+ :dependencies [[org.clojure/clojure "1.5.0-master-SNAPSHOT"]]
+ :dev-dependencies [[jline "0.9.94"]
+ [swank-clojure "1.4.2"]
+ [lein-marginalia "0.7.1"]
+ [lein-multi "1.1.0"]]
+ :multi-deps {"1.2" [[org.clojure/clojure "1.2.0"]]
+ "1.2.1" [[org.clojure/clojure "1.2.1"]]
+ "1.3" [[org.clojure/clojure "1.3.0"]]
+ "1.4" [[org.clojure/clojure "1.4.0"]]}
+ :repositories {"sonatype-oss-public" "https://oss.sonatype.org/content/groups/public/"}
+ :source-path "src/main/clojure"
+ :test-path "src/test/clojure")
View
29 src/main/clojure/clojure/core/cache.clj
@@ -201,11 +201,15 @@
(miss [_ item result]
(let [tick+ (inc tick)]
(if-let [ks (keys lru)]
- (let [k (apply min-key lru ks)]
- (LRUCache. (-> cache (dissoc k) (assoc item result)) ;; eviction case
- (-> lru (dissoc k) (assoc item tick+))
- tick+
- limit))
+ (let [k (apply min-key lru ks) ;; maybe evict case
+ sz (count ks)
+ c (if (>= sz limit)
+ (-> cache (dissoc k) (assoc item result))
+ (assoc cache item result))
+ l (if (>= sz limit)
+ (-> lru (dissoc k) (assoc item tick+))
+ (assoc lru item tick+))]
+ (LRUCache. c l tick+ limit))
(LRUCache. (assoc cache item result) ;; no change case
(assoc lru item tick+)
tick+
@@ -278,10 +282,15 @@
(LUCache. cache (update-in lu [item] inc) limit))
(miss [_ item result]
(if-let [ks (keys lu)]
- (let [k (apply min-key lu ks)]
- (LUCache. (-> cache (dissoc k) (assoc item result)) ;; expulsion case
- (-> lu (dissoc k) (assoc item 0))
- limit))
+ (let [k (apply min-key lu ks) ;; maybe evict case
+ sz (count ks)
+ c (if (>= sz limit)
+ (-> cache (dissoc k) (assoc item result))
+ (assoc cache item result))
+ l (if (>= sz limit)
+ (-> lu (dissoc k) (update-in [item] (fnil inc 0)))
+ (assoc lu item 0))]
+ (LUCache. c l limit))
(LUCache. (assoc cache item result) ;; no change case
(assoc lu item 0)
limit)))
@@ -465,7 +474,7 @@
(.remove rcache r)
(recur (.poll rq)))))
-(defn make-reference [v rq]
+(defn ^{:dynamic true} make-reference [v rq]
(if (nil? v)
(SoftReference. ::nil rq)
(SoftReference. v rq)))
View
42 src/test/clojure/clojure/core/cache/tests.clj
@@ -151,7 +151,23 @@
(let [C (lru-cache-factory {:a 1, :b 2} :threshold 4)]
(are [x y] (= x y)
{:a 1, :b 2, :c 3, :d 4} (-> C (assoc :c 3) (assoc :d 4) .cache)
- {:a 1, :c 3, :d 4, :e 5} (-> C (assoc :c 3) (assoc :d 4) (.hit :c) (.hit :a) (assoc :e 5) .cache)))))
+ {:a 1, :c 3, :d 4, :e 5} (-> C (assoc :c 3) (assoc :d 4) (.hit :c) (.hit :a) (assoc :e 5) .cache))))
+ (testing "regressions against LRU eviction before threshold met"
+ (is (= (-> (clojure.core.cache/lru-cache-factory {} :threshold 2)
+ (assoc :a 1)
+ (assoc :b 2)
+ (assoc :b 3)
+ (assoc :a 4))
+ {:b 3 :a 4}))
+
+ (is (= (-> (clojure.core.cache/lru-cache-factory {} :threshold 3)
+ (assoc :a 1)
+ (assoc :b 2)
+ (assoc :b 3)
+ (assoc :c 4)
+ (assoc :d 5)
+ (assoc :e 6))
+ {:e 6, :d 5, :c 4}))))
(defn sleepy [e t] (Thread/sleep t) e)
@@ -201,7 +217,23 @@
(are [x y] (= x y)
{:a 1, :b 2, :c 3, :d 4} (-> C (assoc :c 3) (assoc :d 4) .cache)
{:a 1, :c 3, :d 4, :e 5} (-> C (assoc :c 3) (assoc :d 4) (.hit :a) (assoc :e 5) .cache)
- {:b 2, :c 3, :d 4, :e 5} (-> C (assoc :c 3) (assoc :d 4) (.hit :b) (.hit :c) (.hit :d) (assoc :e 5) .cache)))))
+ {:b 2, :c 3, :d 4, :e 5} (-> C (assoc :c 3) (assoc :d 4) (.hit :b) (.hit :c) (.hit :d) (assoc :e 5) .cache))))
+ (testing "regressions against LRU eviction before threshold met"
+ (is (= (-> (clojure.core.cache/lu-cache-factory {} :threshold 2)
+ (assoc :a 1)
+ (assoc :b 2)
+ (assoc :b 3)
+ (assoc :a 4))
+ {:b 3 :a 4}))
+
+ (is (= (-> (clojure.core.cache/lu-cache-factory {} :threshold 3)
+ (assoc :a 1)
+ (assoc :b 2)
+ (assoc :b 3)
+ (assoc :c 4)
+ (assoc :d 5)
+ (assoc :e 6))
+ {:e 6, :d 5, :b 3}))))
;; # LIRS
@@ -367,9 +399,9 @@ N non-resident HIR block
(deftest test-soft-cache
(let [ref (atom nil)
old-make-reference make-reference]
- (with-redefs [make-reference (fn [& args]
- (reset! ref (apply old-make-reference args))
- @ref)]
+ (binding [make-reference (fn [& args]
+ (reset! ref (apply old-make-reference args))
+ @ref)]
(let [old-soft-cache (soft-cache-factory {:foo1 :bar})
r @ref
soft-cache (assoc old-soft-cache :foo2 :baz)]
Please sign in to comment.
Something went wrong with that request. Please try again.