Pet*_*lák 23 optimization haskell inline ghc
我有一个模块,它收集并导出一些小函数,例如:
fromEither :: (MonadError e m) => Either e a -> m a
fromEither = either throwError return
Run Code Online (Sandbox Code Playgroud)
要么
withError :: MonadError e m => (e -> e) -> m a -> m a
withError = flip catchError (throwError . f)
Run Code Online (Sandbox Code Playgroud)
让它们内联是个好主意,因为在专门研究MonadError它的特定实例之后,可能会有很多代码被优化掉.
GHC的文件说:
GHC(与
-O往常一样)尝试内联(或"展开")"足够小"的函数/值,从而避免调用开销并可能暴露其他更精彩的优化.通常情况下,如果GHC决定函数"太昂贵"而无法内联,它将不会这样做,也不会导出其他模块使用的展开.
这是否意味着这些函数最有可能被视为具有INLINE编译指示(即它们在接口文件中记录的非优化RHS)?或者我必须添加INLINE自己?添加它会改变什么(假设GHC决定它们"足够小")?
我不介意GHC决定不介绍我的一些功能,如果它觉得它们太贵了,但总的来说我想让它们内联而不会污染我的源代码并添加INLINE到处.
Joa*_*ner 19
根据我的经验,如果有意义的话,这些小功能将自动并跨模块边界内联.
您可以通过运行ghc --show-iface生成的.hi-File 来检查GHC是否决定使其成为可能.如果它Unfolding在下面的示例中说明了某些内容,则在使用此模块时,该函数可能会内联:
$ ghc --show-iface /usr/lib/ghc/base-4.6.0.1/Data/Either.hi
Magic: Wanted 33214052,
got 33214052
...
38da29044ff77a85b08cebca1fed11ad
either :: forall a c b.
(a -> c) -> (b -> c) -> Data.Either.Either a b -> c
{- Arity: 3, HasNoCafRefs, Strictness: LLS,
Unfolding: (\ @ a
@ c
@ b
f :: a -> c
ds :: b -> c
ds1 :: Data.Either.Either a b ->
case ds1 of wild {
Data.Either.Left x -> f x Data.Either.Right y -> ds y }) -}
Run Code Online (Sandbox Code Playgroud)
我想补充Joachim的答案,模块中的函数数量也会影响是否ghc导出它们.例如,当我开始向同一模块添加几个不相关的函数时,Pipes.Preludefrom pipes会显示几个函数的减速.将INLINABLEpragma 添加到这些函数可以恢复原始速度.