This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-05-20
Channels
I may suffer from a fundamental misunderstanding of the way lazy sequences work, but I expected this to scale linearly (`O(n)`) in time and to use constant (`O(1)`) stack (because of lazy-seq
) and constant (`O(1)`) heap (because of the Clojure compiler’s aggressive clearing of closed-over locals):
Bills-MacBook-Air:java-garbage-test Bill$ clojure -J-Xmx100m
Clojure 1.9.0
user=> (def naturals (iterate inc 1))
#'user/naturals
user=> (for [n [1e3 1e4 1e5 1e6 1e7]]
(time (first (drop n naturals))))
("Elapsed time: 10.291044 msecs"
"Elapsed time: 21.7011 msecs"
"Elapsed time: 87.925216 msecs"
"Elapsed time: 5276.022119 msecs"
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
…
Without looking at actual heap numbers it seems like this must be consuming heap proportional to n
, i.e. O(n)
or worse. If it were simply generating garbage at a rapid pace, then GC would eventually catch up before throwing the OutOfMemoryError
right?
What would Alan Jay Perlis say?i get the same results as you when i def naturals
. however if i do the same thing with (time (first (drop n (iterate inc 1))))
i get speedy results. i think this is the result of the realizing (and remembering) the naturals
thank you @dpsutton!
Bills-MacBook-Air:java-garbage-test Bill$ clojure -J-Xmx100m
Clojure 1.9.0
user=> (defn naturals [] (iterate inc 1))
#'user/naturals
user=> (for [n [1e3 1e4 1e5 1e6 1e7]]
(time (first (drop n (naturals)))))
("Elapsed time: 12.95582 msecs"
"Elapsed time: 23.540556 msecs"
"Elapsed time: 236.42463 msecs"
"Elapsed time: 388.825766 msecs"
"Elapsed time: 1883.665229 msecs"
1001 10001 100001 1000001 10000001)