[GHC] #2236: Deep stacks make execution time go through the roof

GHC trac at galois.com
Fri Apr 25 04:39:49 EDT 2008


#2236: Deep stacks make execution time go through the roof
-----------------------------------------+----------------------------------
    Reporter:  simonpj                   |       Owner:         
        Type:  run-time performance bug  |      Status:  new    
    Priority:  normal                    |   Milestone:         
   Component:  Compiler                  |     Version:  6.8.2  
    Severity:  normal                    |    Keywords:         
  Difficulty:  Unknown                   |    Testcase:         
Architecture:  Unknown                   |          Os:  Unknown
-----------------------------------------+----------------------------------
 In the code below, switching from `mapM_` to `mapM` causes a 20x change in
 execution time.   The code being executed is very very similar (try
 `-ddump-simpl`), and the number of bytes allocated is not dissimilar.  But
 the GC time is dramatically more (presumably because we are repeatedly
 scanning a very deep stack) and, more puzzlingly, the MUT time is much
 more too.

 It all seems to be to do with the stack depth.  Not only that, but I think
 the effect is non-linear: doubling n from 200k to 400k nearly quadruples
 runtime.  Doubling again to 800k makes it say 'Killed'.

 {{{
 module Main(main) where

 import System.IO
 import System.IO (openFile, IOMode(..), hPutStr)

 n = 200000::Int

 main = main_fast


 main_slow = do  -- Use mapM
   h <- openFile "bardump2" WriteMode
   mapM (do_it h) testlst

 main_fast = do  -- Use mapM_
   h <- openFile "bardump2" WriteMode
   mapM_ (do_it h) testlst

 do_it h x = hPutStr h "yes"

 testlst = [1..n]
 }}}

 Thanks to Ben for identifying this.  Below are some figures
 {{{
 --------------------------------------
     main = main_fast, N= 300,000

 251,371,168 bytes allocated in the heap
  14,041,824 bytes copied during GC (scavenged)
       1,504 bytes copied during GC (not scavenged)
   8,413,184 bytes maximum residency (5 sample(s))

         448 collections in generation 0 (  2.00s)
           5 collections in generation 1 (  0.01s)

          17 Mb total memory in use

   INIT  time    0.00s  (  0.00s elapsed)
   MUT   time    1.17s  (  1.18s elapsed)
   GC    time    2.01s  (  2.03s elapsed)
   EXIT  time    0.00s  (  0.00s elapsed)
   Total time    3.18s  (  3.22s elapsed)

   %GC time      63.3%  (63.1% elapsed)

   Alloc rate    215,201,590 bytes per MUT second

   Productivity  36.7% of total user, 36.2% of total elapsed

 --------------------------------------
     main = main_slow, N= 300,000

 227,615,792 bytes allocated in the heap
      49,224 bytes copied during GC (scavenged)
       1,440 bytes copied during GC (not scavenged)
      40,960 bytes maximum residency (1 sample(s))

         435 collections in generation 0 (  0.00s)
           1 collections in generation 1 (  0.00s)

           1 Mb total memory in use

   INIT  time    0.00s  (  0.00s elapsed)
   MUT   time    0.15s  (  0.15s elapsed)
   GC    time    0.00s  (  0.00s elapsed)
   EXIT  time    0.00s  (  0.00s elapsed)
   Total time    0.15s  (  0.16s elapsed)

   %GC time       0.0%  (1.8% elapsed)

   Alloc rate    1,537,851,022 bytes per MUT second

   Productivity 100.0% of total user, 95.4% of total elapsed

 ---------------------------------------------
           Non-linear effect

 n      fast/slow        Mut     GC      Tot
 400k    fast            0.19    0       0.2
         slow            2.14    3.64    5.78

 200k    fast            0.09    0       0.09
         slow            0.48    0.96    1.44
 }}}

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2236>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the Glasgow-haskell-bugs mailing list