Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Profiled this example of yours and it seems that the class <code>Stream</code> (well... some anonymous function related to it - forgot its name as visualvm crashed on me) occupies most of the heap. <strike>It's related to the fact that <code>Stream</code>s in Scala do leak memory - see <a href="http://lampsvn.epfl.ch/trac/scala/ticket/692" rel="nofollow noreferrer">Scala Trac #692</a>. Fixes are due in Scala 2.8.</strike>. <b>EDIT:</b> <a href="https://stackoverflow.com/users/53013/daniel">Daniel</a>'s comment rightly pointed out that it is not related to this bug. It's because "<code>val ints</code> points to the Stream head, the garbage collector can't collect anything" [<a href="https://stackoverflow.com/users/53013/daniel">Daniel</a>]. I found the comments in this bug report nice to read though, in relation to this question.</p> <p>In your add function, you are holding a reference to <code>a.head</code>, therefore the garbage collector cannot collect the head, leading to a stream that holds 9999998 elements in the end, which cannot be GC-ed.</p> <p>[A little interlude]</p> <p>You may also keep copies of the tails you keep passing, I am <em>not</em> sure how <code>Stream</code>s deal with that. If you would use a list, tails would <em>not</em> be copied. For example:</p> <pre><code>val xs = List(1,2,3) val ys = 1 :: xs val zs = 2 :: xs </code></pre> <p>Here, both <code>ys</code> and <code>zs</code> 'share' the same tail, at least heap-wise (<code>ys.tail eq zs.tail</code>, aka reference equality yields <code>true</code>). </p> <p>[This little interlude was to make the point that passing a lot of tails is not a really bad thing in principle :), they are not copied, at least for lists]</p> <p>An alternative implementation (which runs quite fast, and I think it is more clear than the pure functional one) is to use an imperative approach:</p> <pre><code>def addTo(n: Int, init: Int): Long = { var sum = init.toLong for(i &lt;- 1 to n) sum += i sum } scala&gt; addTo(9999998, 0) </code></pre> <p>In Scala it is quite OK to use an imperative approach, for performance and clarity (at least to me, this version of <code>add</code> is more clear to its intent). For even more conciseness, you could even write</p> <pre><code>(1 to 9999998).reduceLeft(_ + _) </code></pre> <p>(runs a bit slower, but still reasonable and doesn't blow the memory up)</p> <p>I believe that Clojure might be faster as it is fully functional, therefore more optimisations are possible than with Scala (which blends functional, OO and imperative). I am not very familiar with Clojure though.</p> <p>Hope this helps :)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload