【发布时间】:2014-08-01 22:35:16
【问题描述】:
我有一个使用haskell-src-exts 的程序,为了提高性能,我决定对一些记录字段进行严格限制。这导致性能更差。
这是我要更改的完整模块:
{-# LANGUAGE DeriveDataTypeable, BangPatterns #-}
module Cortex.Hackage.HaskellSrcExts.Language.Haskell.Exts.SrcSpan(
SrcSpan, srcSpan, srcSpanFilename, srcSpanStartLine,
srcSpanStartColumn, srcSpanEndLine, srcSpanEndColumn,
) where
import Control.DeepSeq
import Data.Data
data SrcSpan = SrcSpanX
{ srcSpanFilename :: String
, srcSpanStartLine :: Int
, srcSpanStartColumn :: Int
, srcSpanEndLine :: Int
, srcSpanEndColumn :: Int
}
deriving (Eq,Ord,Show,Typeable,Data)
srcSpan :: String -> Int -> Int -> Int -> Int -> SrcSpan
srcSpan fn !sl !sc !el !ec = SrcSpanX fn sl sc el ec
instance NFData SrcSpan where
rnf (SrcSpanX x1 x2 x3 x4 x5) = rnf x1
请注意,构造SrcSpan 的唯一方法是使用srcSpan 函数,该函数在所有Ints 中都是严格的。
使用此代码,我的程序(抱歉,我不能分享它)在 163 秒内运行。
现在改变一行,例如,
, srcSpanStartLine :: !Int
即,srcSpanStartLine 字段现在被标记为严格。我的程序现在需要 198 秒才能运行。因此,将这一领域设为严格会使运行时间增加约 20%。
这怎么可能? srcSpan 函数的代码应该是相同的,因为它已经很严格了。 srcSpanStartLine 选择器的代码应该更简单一些,因为它不再需要计算。
我已经尝试过开启和关闭-funbox-strict-fields 和-funbox-small-strict-field。它没有任何明显的区别。我正在使用 ghc 7.8.3。
有人见过类似的吗?有什么好主意可能是什么原因造成的?
【问题讨论】:
-
查看 -ddump-simpl 的核心,引入严格性时有一个新的包装器 $WSrcSpanX,我不确定它是否被普遍内联。
-
它应该被内联,因为构造函数的唯一用途是在这个模块中。但即使不是,这对包装器来说似乎是一个非常高的惩罚。
-
把你的程序缩减成你可以分享的东西怎么样?
标签: haskell