[GHC] #8655: Evaluate know-to-terminate-soon thunks

GHC ghc-devs at haskell.org
Wed Jan 15 15:10:10 UTC 2014


#8655: Evaluate know-to-terminate-soon thunks
-------------------------------------+------------------------------------
        Reporter:  nomeata           |            Owner:  nomeata
            Type:  task              |           Status:  new
        Priority:  normal            |        Milestone:
       Component:  Compiler          |          Version:  7.6.3
      Resolution:                    |         Keywords:
Operating System:  Unknown/Multiple  |     Architecture:  Unknown/Multiple
 Type of failure:  None/Unknown      |       Difficulty:  Unknown
       Test Case:                    |       Blocked By:
        Blocking:                    |  Related Tickets:
-------------------------------------+------------------------------------

Comment (by nomeata):

 Ok, next try. This time I modified only `exprOkForSpeculation`: When
 checking an application, it will see if the function has a strictness
 signature with the `Converges` flag, and if all arguments are
 `exprOkForSpeculation` (they might be unlifted, hence speculation would
 also evaluate them), the whole expression is ok for speculation.

 The results are overwhelming....ly minuscule:

 Allocations change exactly as before:
 {{{
           fluid         -45.0%     -0.1%      0.00      0.00     +0.0%
 --------------------------------------------------------------------------------
             Min         -49.5%     -0.1%    -15.4%    -15.4%     -5.7%
             Max         -41.3%     +0.0%    +97.9%    +97.9%     +0.0%
  Geometric Mean         -47.4%     -0.0%    +13.5%    +13.6%     -0.2%
 }}}

 (Ignore code size, one working copy had ticky-ticky enabled. Runtime
 number unusable, machine was not unloaded.)

 I looked at fluid, and it is actually quite nice what happens here: There
 are thunks calling `read_n_val`, which has a definition of `(.., ..)`. CPR
 turns that in to `(# .., .. #)`. So currently, we are allocating a thunk
 for the worker of `read_n_val` (which did not cancel with anything). When
 called, this thunk will allocate a `(..,..)` box, which later is taken
 apart by yet another two thunks, representing `fst ..` resp. `snd ..`.
 After using the `Converges` flag, we immediately call `$wread_n_val`,
 which returns quickly after allocating two thunks. We thereby save the
 allocation of `(..,..)` and the thunks for `fst ..` and `snd ..`.

 What is interesting is that this change did not happen in CorePrep, but
 already in Float Out, directly after the demand analyser. The function
 calling `exprOkForSpeculation` is `lvlCase`.

 I also measured the *static* effect of this change. When compiling GHC,
 the libraries and nofib,
  * master did 205788 calls to `exprOkForSpeculation` from `lvlCase`. Of
 these 7169 (3.48%) returned true, while
  * my branch did 206234 calls to exprOkForSpeculation` from `lvlCase`, of
 these 7245 (3.51%) returned true.

 I doubt that measuring the dynamic effect will give any more insight than
 what we already gain, namely:

 Using `Converges` in `exprOkForSpeculation` is a good idea that does not
 cost much in terms of implementation and does not cause programs to go
 bad. When it kicks in, it does nice things, but in practice the turnout is
 negligibly.

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


More information about the ghc-tickets mailing list