#5715: Inliner fails to inline a function, causing 20x slowdown
-------------------------------------+--------------------------------------
Reporter: bos | Owner:
Type: bug | Status: new
Priority: normal | Component: Compiler
Version: 7.2.1 | Keywords:
Os: Unknown/Multiple | Architecture: Unknown/Multiple
Failure: Runtime performance bug | Testcase:
Blockedby: | Blocking:
Related: |
-------------------------------------+--------------------------------------
Alexey filed [https://github.com/bos/mwc-random/pull/6 a bug against the
mwc-random package recently], indicating a 20x to 40x slowdown on a
function named `uniformRange` - [https://github.com/bos/mwc-
random/blob/d7fda635bdd7a4d03ad8649e26ffa6d2b9b4c400/System/Random/MWC.hs#L487
you can see its source here].
In the original definition, there was an `INLINE` pragma, but Alexey
noticed that it wasn't firing and so performance was predictably terrible.
He added the `SPECIALIZE` pragmas that now follow the body of the
function.
I looked at `-ddump-simpl` output with the `SPECIALIZE` pragmas removed,
and sure enough there are no inlining annotations on the function.
The whole purpose of `uniformRange` is to be used in instance declarations
such as the following:
{{{
instance Variate Int8 where
uniform = uniform1 fromIntegral
uniformR = uniformRange
{-# INLINE uniform #-}
{-# INLINE uniformR #-}
}}}
I have a suspicion that what's going on is that GHC's inliner is declining
to do anything because some call site or other (or perhaps several?) isn't
fully saturated.
The behaviour of the new inliner is subtle to understand at times - it's
not at all obvious when I should rewrite an instance like this, just to
satisfy it:
{{{
instance Variate Int8 where
uniform = uniform1 fromIntegral
uniformR inliner sacrifice = uniformRange inliner sacrifice
{-# INLINE uniform #-}
{-# INLINE uniformR #-}
}}}
Saturating as above turned out to be the solution to the performance
problem. I've been able to remove the `SPECIALIZE` pragmas. However, I'm
still worried.
It would be helpful if GHC had a mode that dumped out when (and why)
inlinings do *not* take place on functions that have been annotated with
`INLINE`, because I'm surely not the only person who gets caught by this.
Also, aesthetically I find that saturating an application as above makes
for tricky-to-read "why are those arguments there?" code, sort of the
inliner's version of the dreaded monomorphism restriction: a lexical tic
that's tremendously important, but for reasons that most readers will not
know about.
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/5715>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs