Created
August 16, 2011 18:28
-
-
Save sjl/1149787 to your computer and use it in GitHub Desktop.
Clojure Delay + GC Question
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn random-byte-array | |
"Return a large byte-array of random bytes." | |
[] | |
(byte-array (map byte | |
(take (* 1024 100) | |
(cycle [(rand-int 100) (rand-int 100) (rand-int 100)]))))) | |
(defn dtest [arr] | |
(delay (alength arr))) | |
(def testlens (doall (map dtest (repeatedly 5 random-byte-array)))) | |
; We now have a non-lazy sequence of 5 delay elements, each of which should be | |
; referencing a big byte array. | |
; | |
; [ (delay ...), (delay ...), ... ] | |
; | | | |
; v v | |
; [bytes...] [bytes...] | |
; Force all the delays. | |
(dorun (map force testlens)) | |
; Ideally the elements in the testlens map would no longer reference the byte arrays, | |
; so they could be gabage collected. | |
; | |
; [ (delay ...), (delay ...), ... ] | |
; | | | |
; v v | |
; cached result cached result | |
; | |
; [bytes...] [bytes...] <---- Ready for GC | |
(System/gc) | |
(println | |
; Each time through this loop we'll build a vector of 5 delays pointing to big | |
; arrays, and force them. | |
; | |
; If the arrays aren't referenced after the force we should be fine, because the | |
; system can GC the old byte-arrays when it needs space for new ones. | |
; | |
; If they ARE still referenced we'll keep consuming memory until we're done with | |
; the entire loop (and run out using the default heap size). | |
(loop [n 1000 | |
lensets []] | |
(if (= n 0) | |
lensets | |
(let [delayed-len-list (doall (map dtest | |
(repeatedly 5 random-byte-array)))] | |
(println n) | |
(recur (dec n) | |
(conj lensets (doall (map force delayed-len-list)))))))) | |
; When I ran this I didn't run out of memory, so it seems delays remove the | |
; references to their args once they cache the value. | |
; | |
; Looking at https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Delay.java#L30-37 | |
; seems to confirm this theory. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment