[GHC] #14052: Significant GHCi speed regression with :module and `let` in GHC 8.2.1

GHC ghc-devs at haskell.org
Sat Jul 29 06:39:33 UTC 2017


#14052: Significant GHCi speed regression with :module and `let` in GHC 8.2.1
-------------------------------------+-------------------------------------
        Reporter:  RyanGlScott       |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  high              |            Milestone:
       Component:  GHCi              |              Version:  8.2.1-rc2
      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:                    |
-------------------------------------+-------------------------------------
Description changed by RyanGlScott:

Old description:

> I recently noticed that the performance of `doctest` in GHC 8.2.1 can be
> much, much worse than in previous versions of 8.0.2. So bad, in fact,
> that a project with 865 `doctest` examples takes about three hours to
> complete in 8.2.1, whereas it would only take 8 seconds in 8.0.2.
>
> To reproduce this issue in a fairly minimal way, you can use the
> following script to generate a file which simulates what `doctest` is
> doing:
>
> {{{#!hs
> -- GenExample.hs
> module Main where
>
> import Control.Monad
>
> import System.Environment
> import System.Exit
> import System.IO
>
> main :: IO ()
> main = do
>   args <- getArgs
>   case args of
>     n:_ -> genExamples (read n)
>     _ -> do hPutStrLn stderr "usage: runghc GenExamples.hs <num-
> examples>"
>             exitWith $ ExitFailure 1
>
> genExamples :: Int -> IO ()
> genExamples nExamples = do
>   putStrLn ":l Foo"
>   ireplicateA_ nExamples genExample
>
> genExample :: Int -> IO ()
> genExample i = putStr $ unlines
>   [ ":m *Foo"
>   , "example : \"expr" ++ show i ++ "\""
>   , "let foo = it"
>   , "\"marker\""
>   , "let it = foo"
>   ]
>
> ireplicateA_ :: Applicative m => Int -> (Int -> m a) -> m ()
> ireplicateA_ cnt0 f =
>     loop cnt0 0
>   where
>     loop cnt n
>         | cnt <= 0  = pure ()
>         | otherwise = f n *> (loop (cnt - 1) $! (n + 1))
> }}}
>
> You'll also need this file:
>
> {{{#!hs
> -- Foo.hs
> module Foo where
>
> example :: Char
> example = 'a'
> }}}
>
> First, use `GenExample` to generate a GHCi script:
>
> {{{
> $ runghc GenExample.hs 500 > Example.script
> }}}
>
> Now you can run the script like so (using GHCi 8.0.2 as an example):
>
> {{{
> $ /opt/ghc/8.0.2/bin/ghci -ghci-script Example.script Foo.hs
> }}}
>
> With GHCi 8.0.2, this takes about three seconds. But with GHCi 8.2.1,
> this takes about 35 seconds!

New description:

 I recently noticed that the performance of `doctest` in GHC 8.2.1 (see the
 corresponding [https://github.com/sol/doctest/issues/170 doctest issue])
 can be much, much worse than in previous versions of 8.0.2. So bad, in
 fact, that a project with 865 `doctest` examples takes about three hours
 to complete in 8.2.1, whereas it would only take 8 seconds in 8.0.2.

 To reproduce this issue in a fairly minimal way, you can use the following
 script to generate a file which simulates what `doctest` is doing:

 {{{#!hs
 -- GenExample.hs
 module Main where

 import Control.Monad

 import System.Environment
 import System.Exit
 import System.IO

 main :: IO ()
 main = do
   args <- getArgs
   case args of
     n:_ -> genExamples (read n)
     _ -> do hPutStrLn stderr "usage: runghc GenExamples.hs <num-examples>"
             exitWith $ ExitFailure 1

 genExamples :: Int -> IO ()
 genExamples nExamples = do
   putStrLn ":l Foo"
   ireplicateA_ nExamples genExample

 genExample :: Int -> IO ()
 genExample i = putStr $ unlines
   [ ":m *Foo"
   , "example : \"expr" ++ show i ++ "\""
   , "let foo = it"
   , "\"marker\""
   , "let it = foo"
   ]

 ireplicateA_ :: Applicative m => Int -> (Int -> m a) -> m ()
 ireplicateA_ cnt0 f =
     loop cnt0 0
   where
     loop cnt n
         | cnt <= 0  = pure ()
         | otherwise = f n *> (loop (cnt - 1) $! (n + 1))
 }}}

 You'll also need this file:

 {{{#!hs
 -- Foo.hs
 module Foo where

 example :: Char
 example = 'a'
 }}}

 First, use `GenExample` to generate a GHCi script:

 {{{
 $ runghc GenExample.hs 500 > Example.script
 }}}

 Now you can run the script like so (using GHCi 8.0.2 as an example):

 {{{
 $ /opt/ghc/8.0.2/bin/ghci -ghci-script Example.script Foo.hs
 }}}

 With GHCi 8.0.2, this takes about three seconds. But with GHCi 8.2.1, this
 takes about 35 seconds!

--

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


More information about the ghc-tickets mailing list