[GHC] #16034: Quadratic GC slowdown using RTS debug

GHC ghc-devs at haskell.org
Tue Dec 11 22:39:22 UTC 2018


#16034: Quadratic GC slowdown using RTS debug
-------------------------------------+-------------------------------------
           Reporter:  remyo          |             Owner:  (none)
               Type:  bug            |            Status:  new
           Priority:  normal         |         Milestone:
          Component:  Runtime        |           Version:  8.6.3
  System                             |
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  None/Unknown
  Unknown/Multiple                   |
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 Hello,

 Under some conditions of heavy heap usage, I seem to experience a
 quadratic slowdown due to GC using the debugging RTS only (for example, in
 the context of ticky profiling).

 I have been able to reproduce it using the following program (depending on
 the aeson library):
 {{{#!hs
 import Data.Aeson (eitherDecode, Value)
 import qualified Data.ByteString.Lazy as BL
 import Data.Maybe (catMaybes)
 import System.Directory (listDirectory)
 import System.FilePath ( (</>) )

 main :: IO()
 main = do
     let dir = "data"
     files <- listDirectory dir
     values <- catMaybes <$> mapM (readF dir) files
     print $ length values

 readF :: FilePath -> FilePath -> IO (Maybe Value)
 readF dir fp = do
     print (dir </> fp)
     blob <- BL.readFile (dir </> fp)
     case eitherDecode blob of
         Left _ -> return Nothing
         Right v -> return $ Just $! v
 }}}

 Here data is a directory filled with (identical) JSON files. See the
 attached Python script for the proposed dataset.

 {{{
 $ ghc -O -dynamic -o main Main.hs
 $ ./main +RTS -s
 ...
   18,583,045,600 bytes allocated in the heap
    6,334,338,280 bytes copied during GC
      975,763,072 bytes maximum residency (14 sample(s))
        6,986,112 bytes maximum slop
              930 MB total memory in use (0 MB lost due to fragmentation)

                                      Tot time (elapsed)  Avg pause  Max
 pause
   Gen  0     17727 colls,     0 par    2.596s   2.597s     0.0001s
 0.0006s
   Gen  1        14 colls,     0 par    2.422s   2.422s     0.1730s
 0.7947s

   INIT    time    0.000s  (  0.000s elapsed)
   MUT     time    3.349s  (  3.351s elapsed)
   GC      time    5.019s  (  5.020s elapsed)
   EXIT    time    0.000s  (  0.000s elapsed)
   Total   time    8.368s  (  8.371s elapsed)

   %GC     time       0.0%  (0.0% elapsed)

   Alloc rate    5,548,968,539 bytes per MUT second

   Productivity  40.0% of total user, 40.0% of total elapsed
 }}}

 {{{
 $ ghc -O -dynamic -debug -o main.debug Main.hs
 $ ./main +RTS -s
 ...
   18,583,045,600 bytes allocated in the heap
    6,334,332,424 bytes copied during GC
      975,763,072 bytes maximum residency (14 sample(s))
        6,986,112 bytes maximum slop
              930 MB total memory in use (0 MB lost due to fragmentation)

                                      Tot time (elapsed)  Avg pause  Max
 pause
   Gen  0     17727 colls,     0 par   172.941s  172.959s     0.0098s
 0.0459s
   Gen  1        14 colls,     0 par    9.532s   9.532s     0.6808s
 3.2061s

   INIT    time    0.000s  (  0.000s elapsed)
   MUT     time    5.020s  (  5.017s elapsed)
   GC      time  182.473s  (182.491s elapsed)
   EXIT    time    0.000s  (  0.000s elapsed)
   Total   time  187.492s  (187.508s elapsed)

   %GC     time       0.0%  (0.0% elapsed)

   Alloc rate    3,701,999,827 bytes per MUT second

   Productivity   2.7% of total user, 2.7% of total elapsed
 }}}

 In debug mode, the runtime is almost quadratic:
 {{{
 Nb of files   Duration (non-debug)  Duration (debug)
  100            0.8s                   2.8s
  200            1.6s                   8.8s
  400            3.2s                  27.6s
 1000            8.2s                 168.9s
 }}}

 The problem can be seen with either GHC 8.6.3 (here on Archlinux, with
 aeson 1.4.2.0) but was also observed using GHC 8.4.4, with static
 binaries, using "stack". I was able to reproduce with both threaded and
 non-threaded mode.

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


More information about the ghc-tickets mailing list