[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