Reputation: 3519
Different infinite loops (at the REPL, clojure 1.7.0):
(count (range)) ; ~100% of 1 CPU, as expected.
(def x (range))
(count x) ; Over 7 CPUs maxed out, on a 4-core machine (hyper threading?).
The lower loop also hogs memory, so incessant GC may be the reason for the huge CPU usage. But why would there be such a memory difference in the first place?
Upvotes: 1
Views: 109
Reputation: 1665
The function range
creates a lazy sequence. Lazy sequences create their elements only on-demand. If the beginning of the lazy seq is tied to some variable (either locally with let
or globally with def
), the seq will cache all its elements and thus consume memory. This is commonly referred to as "holding onto the head of a sequence".
That's why your second example consumes a lot of memory.
I would expect that an analysis with jvisualvm will show that it is not clojure itself that consumes the CPU cycles but the JVM trying to cope with the increasing memory usage.
Finally, count
traverses the whole sequence, thereby realizing all elements. In case of just (range)
the sequence would never end, it gets stopped when no more memory is available.
Upvotes: 2