[GHC] #12150: Compile time performance degradation on code that uses undefined/error with CallStacks

GHC ghc-devs at haskell.org
Sat Aug 27 21:58:18 UTC 2016


#12150: Compile time performance degradation on code that uses undefined/error with
CallStacks
-------------------------------------+-------------------------------------
        Reporter:  thomie            |                Owner:
            Type:  bug               |               Status:  new
        Priority:  high              |            Milestone:  8.0.2
       Component:  Compiler          |              Version:  8.0.1
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Compile-time      |  Unknown/Multiple
  performance bug                    |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  #10844            |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by thomie):

 gridaphobe: I was investigating a report of some (other) compile time
 regression (I don't remember which ticket or which program). I tried to
 find a small reproducible example, deleting as much code as possible, and
 replacing function bodies with `undefined`.

 I then noticed something fishy was going on with `undefined` itself, and
 came up with the above example. So the above example doesn't look anything
 like the original program I was investigating.

 == Constant factor performance degradation ==

 The measurements presented in the description make it seem like 7.10.3
 took `O(1)` seconds to compile the program (where `n` is the number of
 guards), while 8.0.1 took `O(n)` seconds. This is not the case: **both
 versions of GHC need `O(n)` time.**

 Running the program from the description a bit longer:

 7.10.3:
 {{{
 N clauses : time (s)
 10        : 1.39
 20        : 0.28
 40        : 0.30
 80        : 0.28
 160       : 0.36
 320       : 0.39
 640       : 0.53
 1280      : 0.74
 2560      : 1.17
 5120      : 2.11
 10240     : 4.21
 20480     : 8.18
 40960     : 17.15
 }}}

 So we're should really just be looking at constant factor performance
 differences.

 == Timing results ==
 Time (s) to compile the program with 1000 `bool = f` clauses with
 different versions of undefined and error:
 ||= bool/f= =||= ghc-7.10.3 =||= ghc-8.0.1 =||
 || old undefined || 0.6 || 0.8 ||
 || new undefined || 0.6 || 18 ||
 || myUndef :: a; myUndef = old undefined || 2.0 || 2.1 ||
 || myUndef :: a; myUndef = new undefined || 2.0 || 4.2 ||
 || old error || 6 || 6.5 ||
 || new error || 6 || 5 ||


 === Quotes ===

 > the CallStack-free variant [`myUndef :: a`] behaves just like the old
 undefined
 No, it is still 5x slower (4.2 vs 0.8 seconds).

 > if I [..] use the *old* error instead of undefined, I get a similar
 behavior to the *new* undefined
 No. 8.0.1 still takes 3x longer to compile the (new) `undefined` than it
 is to compile the (old or new) `error` (18 vs 5-6 seconds).

 > When we remove the CallStacks from undefined, GHC manages to optimize
 away the entire set of guards!
 Hmm, maybe the whole example is flawed.

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


More information about the ghc-tickets mailing list