【问题标题】:Why is it common to mark record fields with UNPACK and strictness?为什么使用 UNPACK 和严格标记记录字段很常见?
【发布时间】:2018-05-22 05:36:25
【问题描述】:

我注意到这种模式在 Haskell 库中很常见:

data Foo = Foo { field :: {-# UNPACK #-} !Sometype } 

例如UNPACKing 字段的类型并使其严格。

我明白 pragma 和 annotation 的作用是什么,但我不明白为什么它如此普遍:我在 Haskell 中编程已有 15 年,很少使用严格注释,也从未使用过 UNPACK pragma。

如果这个成语这么有用,为什么不让它不那么“丑”呢?

【问题讨论】:

标签: haskell ghc


【解决方案1】:

pragma 可能有点丑陋,但它在其他地方避免了很多 more 丑陋。当性能至关重要时,程序员通常需要为数据构造函数选择特定的形状。假设我有

data Point = Point Int Int
data Segment = Segment Point Point

这很符合逻辑,但它有一堆额外的间接性:一个Segment七个 堆对象组成。如果我要处理很多片段,那就太糟糕了。

我可以用手压扁这个单位:

data Segment = Segment Int# Int# Int# Int#

但现在我已经忘记了数字代表点的事实,并且我对段所做的一切都必须涉及相当不方便和奇怪的未装箱操作。

还好有更好的办法:

-- The small strict Int fields will be unpacked by default
-- with any reasonably recent GHC version.
data Point = Point !Int !Int

data Segment = Segment {-# UNPACK #-} !Point {-# UNPACK #-} !Point

这仍然为每个段提供一个堆对象,但我可以使用 Points 和 Ints 并且(通常)依赖编译器很好地拆箱。

【讨论】:

  • 我是否正确理解UNPACK 需要!?并且仅出于性能原因才需要这样做(就内存消耗和/或 GC 开销和/或装箱/拆箱所花费的 CPU 时间而言)?
  • @insitu,是的,只能解压严格的字段。懒惰的人需要那些额外的堆对象来保留语义。是的,UNPACK 只会影响性能。经验法则是小东西应该拆包,大东西不应该拆包,但这真的取决于上下文。
  • 我想我的下一个问题是:为什么对所有记录字段都进行严格规定是很常见的?感谢您的回答。
  • @insitu,原因之一是允许解包。另一个主要是避免空间泄漏和过度分配。懒惰通常要么对性能至关重要,要么对其有害。
猜你喜欢
  • 2015-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多