【问题标题】:Haskell : Using unboxed tuples lead to weird types during heap profilingHaskell:在堆分析期间使用未装箱的元组会导致奇怪的类型
【发布时间】:2012-12-14 18:15:44
【问题描述】:

最初,我有一段代码如下:

data Something = Something !Word32 !Word32

retrieveSomething :: Socket -> IO (Something)
retrieveSomething sock = do
    ...

function sock = do
    (Something x y) <- retrieveSomething sock
    let (a,b,c) = case x of
      0 -> (foo,bar,baz)
      1 -> (foo2,bar2,baz2)
      ...

    doIOwithParams a b c

我使用 -hy -hC"..." RTS 选项对其进行了分析。

查看堆配置文件,我发现使用 3 元组会消耗太多内存,因此我使用了似乎更适合返回多个值的未装箱元组扩展(即(# a,b,c #))。

我或多或少相信堆使用量已经减少,因为我在尝试未装箱的元组之前通过显式调用stuff 对其进行了测试,但是通过这样做,我现在无法观察到不同类型的值在成本中心分配。

为了更清楚地说明这个问题,我可以看到在对没有未装箱元组的应用程序进行分析后,Something 类型(以及其他任何东西)在堆中占用了多少空间值。现在,在堆图上只能看到一种类型,我认为这与我在函数调用中进行的可变哈希表调用有关。

有没有办法解决这个问题?

编辑:虽然未装箱的元组没有出现在配置文件上是完全合理的,但我仍然很困惑为什么使用它们会在函数调用/成本中心隐藏其他所有内容

我尝试过使用显式调用而不是使用未装箱的元组进行分析,如下所示:

    case x of
      0 -> doIOwithParams foo bar baz
      1 -> doIOwithParams foo2 bar2 baz2

除了能够看到 3 元组的开销之外,函数中使用的Something 和所有其他类型也是可见的,这与我使用未装箱元组的情况相反,我只能看到与其他类型相比,几乎不占用空间的节点类型(可能与我正在使用的哈希表相关,也可能不相关)。

【问题讨论】:

  • 你能发布一些代码来重现它吗?我想我没听懂你在说什么。
  • 我对 haskell 了解得不够好,无法给出答案,但在我看来,从你拆箱值的那一刻起,它就不再被标记了,我的直觉是它是信息调试器和分析器用于知道哪个数据是哪个。
  • 阅读有关 unboxed tuples 的文档,似乎它们的使用相当受限于函数返回值,并且它们存储在寄存器或堆栈中,这意味着它们不会显式出现在托管内存区域中。

标签: haskell profiling


【解决方案1】:

我发现使用 3 元组会消耗太多内存,因此我使用了未装箱的元组扩展名(即 (# a,b,c #)),这似乎更适合返回多个值。

只需使用具有严格字段的​​常规数据类型。然后 GHC 可以将它映射到堆栈上的堆或未装箱的元组,因为它认为合适。

data Something = Something {-# UNPACK #-}!Word32 {-# UNPACK #-}!Word32

这具有未装箱元组的所有优点,没有任何缺点。

【讨论】:

    猜你喜欢
    • 2020-04-17
    • 2017-10-09
    • 2020-03-17
    • 1970-01-01
    • 2018-02-17
    • 1970-01-01
    • 2010-09-30
    • 2014-10-15
    • 1970-01-01
    相关资源
    最近更新 更多