[GHC] #15717: Performance regression in for_ alternatives from GHC 8.2.2 to newer GHCs

GHC ghc-devs at haskell.org
Wed Dec 12 21:42:29 UTC 2018


#15717: Performance regression in for_ alternatives from GHC 8.2.2 to newer GHCs
-------------------------------------+-------------------------------------
        Reporter:  nh2               |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:  8.8.1
       Component:  Compiler          |              Version:  8.6.1
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Runtime           |  Unknown/Multiple
  performance bug                    |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by nh2):

 Replying to [comment:3 simonpj]:
 > There are 9 tests in the repro case.  I've lost track of what is what.
 If someone was able to distil out a simple before-and-after on one test

 This part I can answer immediately: I use only `./TraverseMaybePerformance
 8` in the issue description, so that's `test8` form the repro.

 But yes, a smaller test case will make things easier. Here it is:

 {{{
 #!/usr/bin/env stack
 -- stack --resolver lts-11.22 script --optimize
 -- The above one is fast. Slow is:
 -- stack --resolver lts-12.11 script --optimize

 {-# OPTIONS_GHC -Wall #-}

 import           Control.Concurrent (yield)
 import           Control.Monad (when)
 import qualified Data.Text.Lazy as T
 import qualified Data.Foldable as F

 myfor_ :: (Foldable f, Applicative app) => f a -> (a -> app ()) -> app ()
 myfor_ t f =
   case F.toList t of
     [] -> pure ()
     x -> go x
   where
     go [x] = f x
     go (x:xs) = f x *> go xs

 printChars_myfor_ :: Int -> T.Text -> IO ()
 printChars_myfor_ idx t = myfor_ (T.uncons t) $ \(c, t') -> do
   when (idx `mod` 100000 == 0) $ do
     -- Using putStrLn, I observe 2x more allocations with GHC 8.4.3 vs
 8.2.2 (860 vs 460 M)
     --putStrLn $ "Character #" ++ show idx ++ ": " ++ show c
     -- Using yield,    I observe 4x more allocations with GHC 8.4.3 vs
 8.2.2 (860 vs 220 M)
     yield -- the putStrLn isn't necessary, this is enough to trigger the
 regression
   printChars_myfor_ (idx + 1) t'

 main :: IO ()
 main = printChars_myfor_ 1 $ T.replicate 5000000 $ T.singleton 'x'
 }}}

 I even managed to make the regression 4x worse using `yield`.

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


More information about the ghc-tickets mailing list