[GHC] #10069: CPR related performance issue

GHC ghc-devs at haskell.org
Wed Feb 18 14:25:12 UTC 2015


#10069: CPR related performance issue
-------------------------------------+-------------------------------------
        Reporter:  pacak             |                   Owner:
            Type:  bug               |                  Status:  new
        Priority:  normal            |               Milestone:
       Component:  Compiler          |                 Version:  7.10.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 Revisions:
-------------------------------------+-------------------------------------

Comment (by simonpj):

 OK, I looked at the 10x smaller version. Can you attach it to the ticket?
 (180kb is ok I think.)  I could do so, but do not want to upload sensitive
 info.

 I have learned some things (see below).  But to explore solutions I really
 do need a reproducible test case.  So if you untangle dependencies that
 would be really helpful.  It's hard for me to make more progress without
 that. E.g. I want to see the code just before strictness analysis.  I want
 to see the code and strictness for `Trader.Order.Logging.$wa`, which is in
 a different module.

 The rest of this is notes for me or other hackers, to record what I have
 learned.
 I'm certain that difficulty is to do with '''reboxing''' (c.f. #2289).  I
 see a function `processManualOrders` that I believe looks somethign like
 this (before strictness analysis)
 {{{
 pma _ p q r
   = let help x v = case select_deep_field_of p of
                     True  -> ...(help x v')...
                     False -> log_fn x   -- log_fn is lazy in x
     in
     help p r
 }}}

 So the `help` function is not strict in `x`.  But `pma` is strict in `p`
 because of the `(select_deep_field p)`
 in `help`.

 Sadly that means that `p` is passed to `help` in ''boxed'' form (since
 `help` is lazy), but is passed to `pma`
 in ''unboxed'' form (since `pma` is strict).  The result is that `p` is
 re-boxed in the worker for `pma`.
 And `p` is a record with many tens of fields.

 Various things would help here:

  * Running the static argument transformation on `help` would solve the
 problem completely.

  * It probably does not make sense to do worker/wrapper on records with
 huge numbers of fields.  We end up passing arguments in memory anyway,
 just on the stack instead of in the heap.  And the reboxing penalty is
 large.

  * In `Demand.bothUse` I see
 {{{
 bothUse (UProd {}) (UCall {})       = Used
 -- bothUse (UProd {}) Used             = Used  -- Note [Used should win]
 bothUse Used (UProd ux)             = UProd (map (`bothMaybeUsed` useTop)
 ux)
 bothUse (UProd ux) Used             = UProd (map (`bothMaybeUsed` useTop)
 ux)
 bothUse Used _                      = Used  -- Note [Used should win]
 }}}
  Note that commented out line. If `Used` really did win, I think that most
 of this fruitless work would go away.  But it's delicate and I'm sure the
 commented out line was commented out for a reason.

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


More information about the ghc-tickets mailing list