Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The cause of the memory consumption in ghci is not the code of <code>filter</code> or <code>elem</code>. (Although the rewrite rule for <code>filter</code> in <code>GHC.List</code> makes it a little better usually.)</p> <p>Let's look at (part of) the core ghc-7.4.2 produced with <code>-O2</code> (<code>-ddump-simpl</code>). First for <code>r</code>, using <code>GHC.List.filter</code>:</p> <pre><code>Has.r1 :: GHC.Integer.Type.Integer -&gt; [GHC.Integer.Type.Integer] -&gt; [GHC.Integer.Type.Integer] [GblId, Arity=2, Unf=Unf{Src=&lt;vanilla&gt;, TopLvl=True, Arity=2, Value=True, ConLike=True, Cheap=True, Expandable=True, Guidance=IF_ARGS [0 0] 60 30}] Has.r1 = \ (x_awu :: GHC.Integer.Type.Integer) (r2_awv :: [GHC.Integer.Type.Integer]) -&gt; case GHC.Integer.Type.eqInteger x_awu Has.p5 of _ { GHC.Types.False -&gt; r2_awv; GHC.Types.True -&gt; GHC.Types.: @ GHC.Integer.Type.Integer x_awu r2_awv } Has.r :: [GHC.Integer.Type.Integer] [GblId, Str=DmdType, Unf=Unf{Src=&lt;vanilla&gt;, TopLvl=True, Arity=0, Value=False, ConLike=False, Cheap=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] Has.r = GHC.Enum.enumDeltaIntegerFB @ [GHC.Integer.Type.Integer] Has.r1 Has.p3 Has.p2 </code></pre> <p><code>Has.p3</code> is <code>0 :: Integer</code>, and <code>Has.p2</code> is <code>1 :: Integer</code>. The rewrite rules (for <code>filter</code> and <code>enumDeltaInteger</code>) turned it into (with shorter names)</p> <pre><code>r = go fun 0 1 where go foo x d = x `seq` (x `foo` (go foo (x+d) d)) fun n list | n == 1000000000000 = n : list | otherwise = list </code></pre> <p>which could probably be a bit more efficient if <code>fun</code> was inlined, but the point is that the list to be <code>filter</code>ed doesn't exist as such, it was fused away.</p> <p>For <code>p</code> on the other hand, without the rewrite rule(s), we get</p> <pre><code>Has.p1 :: [GHC.Integer.Type.Integer] [GblId, Unf=Unf{Src=&lt;vanilla&gt;, TopLvl=True, Arity=0, Value=False, ConLike=False, Cheap=False, Expandable=False, Guidance=IF_ARGS [] 30 0}] Has.p1 = GHC.Enum.enumDeltaInteger Has.p3 Has.p2 Has.p :: [GHC.Integer.Type.Integer] [GblId, Str=DmdType, Unf=Unf{Src=&lt;vanilla&gt;, TopLvl=True, Arity=0, Value=False, ConLike=False, Cheap=False, Expandable=False, Guidance=IF_ARGS [] 30 0}] Has.p = Has.filter @ GHC.Integer.Type.Integer Has.p4 Has.p1 </code></pre> <p>a top-level CAF for the list <code>[0 .. ]</code> (<code>Has.p1</code>), and <code>Has.filter</code> applied to <code>(== 1000000000000)</code> and the list.</p> <p>So this one does create the actual list to be filtered - thus it's somewhat less efficient.</p> <p>But normally (running a compiled binary), that's no problem in terms of memory consumption, since the list is garbage collected as it is consumed. However, for reasons that are beyond me, ghci does keep the list <code>[0 .. ]</code> around when evaluating <code>p</code> or <code>s</code> (but that has its own copy of <code>[0 .. ]</code>, so it's not unwanted sharing here), as can be gleaned from the <code>-hT</code> heap profile (evaluating <code>s</code>, so there's only one possible source for the list cells. ghci invoked with <code>+RTS -M300M -hT -RTS</code>, so shortly after the memory usage reached 300M, ghci terminated):</p> <p><img src="https://i.stack.imgur.com/DqUBk.png" alt="enter image description here"></p> <p>So the cause of the memory consumption in ghci is the hardcoding of the list to be filtered. If you use <code>Has.filter</code> with a list supplied at the prompt, the memory usage is constant as expected.</p> <p>I'm not sure whether ghci retaining the list <code>[0 .. ]</code> is a bug or intended behaviour.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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