A performance predicament

Richard Eisenberg eir at cis.upenn.edu
Fri Mar 11 16:11:53 UTC 2016

Hi devs,

I'm working on some compiler performance bugs. I've implemented caching for coercion kinds at Phab:D1992. But tests show a net slowdown, which I'm currently investigating. I could abandon this work for 8.0, but it really should show an improvement, and so I'm looking deeper.

A little profiling has shown that the (>>=) operator of the FlatM monad is doing 13% of all allocations on a test program (T3064). The sad thing is that, if I understand correctly, this bind shouldn't do any allocation at all! Here are the relevant definitions:

> newtype FlatM a = FlatM { runFlatM :: FlattenEnv -> TcS a }
> newtype TcS a = TcS { unTcS :: TcSEnv -> TcM a }
> type TcM = TcRn
> type TcRn = TcRnIf TcGblEnv TcLclEnv
> type TcRnIf a b = IOEnv (Env a b)
> newtype IOEnv env a = IOEnv (env -> IO a)

As we can see here, FlatM a is equivalent to (Foo -> Bar -> Baz -> IO a). So working in this monad should just pass around the three parameters without doing any allocation, unless IO's bind operation does allocation. (I assume we use magic to prevent that last piece.) I've tried adding INLINE to the various pieces to no avail.

Am I misunderstanding something fundamental here? I feel like I must be.


PS: The allocation done by FlatM was around before my caching optimization. So I'm working slightly orthogonally to where I started. But if IOEnv is really doing something even slightly slowly, a small tweak here could net massive improvements in overall speed.

More information about the ghc-devs mailing list