【问题标题】:Changing a single record field to be strict leads to worse performance将单个记录字段更改为严格会导致性能下降
【发布时间】: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


【解决方案1】:

通过更多调查,我可以回答我自己的问题。简短的回答是uniplate

答案稍长。在一个地方,我使用 uniplate 来获取 Pat 的孩子(haskell-src-exts 类型的模式)。调用看起来像children p,而这个children 实例的类型是Pat SrcSpanInfo -> [Pat SrcSpanInfo]。所以它没有递归,只是返回一个节点的直接子节点。

Uniplate 使用两种截然不同的方法,具体取决于您操作的类型中是否有严格的字段。如果没有严格的字段,它的速度相当快,如果使用严格的字段,它会切换到使用gfoldl,而且速度非常慢。即使我对单板的使用没有直接涉及严格的领域,它也变慢了。

结论:如果您在任何地方都有严格的领域,请当心单板!

【讨论】:

  • 奇怪的是,geniplate 是否不足以满足您的需求?它不是避免了这个问题并提供了更好的性能吗?
  • Geniplate 没有children 功能。我在其他任何地方都使用 Geniplate。
猜你喜欢
  • 1970-01-01
  • 2018-07-02
  • 2012-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多