Haskell:在堆分析期间,使用未装箱的元组会导致奇怪的类型

时间:2012-12-30 00:18:43

标签: haskell profiling

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

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(和其他任何东西)类型的空间值有多少。现在,在堆图上只能看到一种类型,我认为这与我在函数调用中进行的可变哈希表调用有关。

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

编辑:虽然未装箱的元组没有出现在配置文件中,但我仍然感到困惑的是,为什么使用它们会在函数调用/成本中心中隐藏其他所有。< / p>

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

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

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

1 个答案:

答案 0 :(得分:3)

  

我曾经看到使用3元组消耗的内存过多,所以我使用了未装箱的元组扩展(即(#a,b,c#)),这似乎更适合返回多个值。

只需使用具有严格字段的​​常规数据类型即可。然后GHC可以根据需要将其映射到堆栈上的堆或未装箱的元组。

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

这具有未装箱元组的所有好处,而且没有任何缺点。