1

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?

1
  • 3
    count does not retain data while it counts. But with def the materialized data is retained by the x variable. Commented Jul 14, 2016 at 23:12

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

@KevinKostlan because a sequence may produce an element that contains, say, current time. Which means that if you don't store materialized data then the second iteration over the same sequence would produce different results.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.