Performance 为什么专门化具有标识的一元函数比手动编写效率低?

Performance 为什么专门化具有标识的一元函数比手动编写效率低?,performance,haskell,monads,higher-order-functions,Performance,Haskell,Monads,Higher Order Functions,我需要两个高阶函数,一个取无副作用函数,另一个取一元函数作为参数: frobM :: Monad m => (a -> m a) -> b -> m b frob :: (a -> a) -> b -> b 它们非常相似,第二个函数可以用第一个函数表示: frob f = runIdentity . frobM (return . f) 我希望这与“手工”编写frob一样高效,因为Identity是一种新类型,应该在编译时删除。然而,无论怎样,性能仍

我需要两个高阶函数,一个取无副作用函数,另一个取一元函数作为参数:

frobM :: Monad m => (a -> m a) -> b -> m b
frob :: (a -> a) -> b -> b
它们非常相似,第二个函数可以用第一个函数表示:

frob f = runIdentity . frobM (return . f)
我希望这与“手工”编写
frob
一样高效,因为
Identity
是一种新类型,应该在编译时删除。然而,无论怎样,性能仍然受到影响,这一标准微观基准证明了这一点:

import Criterion.Main (bench, defaultMain, nf)
import Data.Functor.Identity (Identity (runIdentity))

main :: IO ()
main = defaultMain
       [ bench "frob"  $ nf (frob (+23)) 42
       , bench "frob'" $ nf (frob' (+23)) 42
       ]

-- | Generalized function
frobM :: Monad m => (Int -> m Int) -> Int -> m Int
frobM f n = f $ 2^n `mod` 1024

-- | Specialized function based on the general function
frob' :: (Int -> Int) -> Int -> Int
frob' f = runIdentity . frobM (return . f)

-- | "Hand written" specialized function.
frob :: (Int -> Int) -> Int -> Int
frob f n = f $ 2^n `mod` 1024
输出:

benchmarking frob
time                 676.1 ns   (673.5 ns .. 678.9 ns)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 675.7 ns   (673.3 ns .. 677.3 ns)
std dev              6.600 ns   (5.984 ns .. 7.324 ns)

benchmarking frob'
time                 706.2 ns   (705.0 ns .. 707.9 ns)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 705.7 ns   (704.5 ns .. 707.4 ns)
std dev              4.630 ns   (3.729 ns .. 6.226 ns)

这是什么原因造成的?有没有办法使
frob'
frob
一样高效?

无法复制。使用
ghc-7.10-O2
,我得到
frob
frob'
的时间为116纳秒;使用
-O
时,每台为125纳秒。(您确实使用了优化标志,对吗?)只是为了确保:当您打开优化时,您还使用了
-fforce recomp
?否则,除非文件本身已更改,否则GHC将不会执行任何操作。@leftaroundabout是这样做的!万分感谢!通常,这种情况在我身上发生过好几次。@leftaroundabout听起来像是一个答案:)无法复制。使用
ghc-7.10-O2
,我得到
frob
frob'
的时间为116纳秒;使用
-O
时,每台为125纳秒。(您确实使用了优化标志,对吗?)只是为了确保:当您打开优化时,您还使用了
-fforce recomp
?否则,除非文件本身已更改,否则GHC将不会执行任何操作。@leftaroundabout是这样做的!万分感谢!“很普通,这在我身上发生过好几次。@leftaroundabout听起来像是一个答案:)