
#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