Performance degradation when factoring out common code
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
Hello, I've had a similar problem that's been fixed in 8.2.1: https://ghc.haskell.org/trac/ghc/ticket/12603 You can also use some extreme global flags, such as ghc-options: -fexpose-all-unfoldings -fspecialise-aggressively to get most the GHC subtlety and shyness out of the way when experimenting. Good luck Mikolaj On Fri, Sep 8, 2017 at 11:21 AM, Harendra Kumar <harendra.kumar@gmail.com> wrote:
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
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
participants (2)
-
Harendra Kumar -
Mikolaj Konarski