Performance degradation when factoring out common code

Harendra Kumar harendra.kumar at gmail.com
Fri Sep 8 09:21:09 UTC 2017


Hi,

I have this code snippet for the bind implementation of a Monad:

    AsyncT m >>= f = AsyncT $ \_ stp yld ->
        let run x = (runAsyncT x) Nothing stp yld
            yield a _ Nothing  = run $ f a
            yield a _ (Just r) = run $ f a <> (r >>= f)
        in m Nothing stp yield

I want to have multiple versions of this implementation parameterized by a
function, like this:

bindWith k (AsyncT m) f = AsyncT $ \_ stp yld ->
    let run x = (runAsyncT x) Nothing stp yld
        yield a _ Nothing  = run $ f a
        yield a _ (Just r) = run $ f a `k` (bindWith k r f)
    in m Nothing stp yield

And then the bind function becomes:

(>>=) = bindWith (<>)
But this leads to a performance degradation of more than 10%. inlining does
not help, I tried INLINE pragma as well as the "inline" GHC builtin. I
thought this should be a more or less straightforward replacement making
the second version equivalent to the first one. But apparently there is
something going on here that makes it perform worse.

I did not look at the core, stg or asm yet. Hoping someone can quickly
comment on it. Any ideas why is it so? Can this be worked around somehow?

Thanks,
Harendra
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-devs/attachments/20170908/d7c6a11f/attachment-0001.html>


More information about the ghc-devs mailing list