
#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