如何在使用GHC编译的Haskell函数中找到分配?

如何在使用GHC编译的Haskell函数中找到分配?,haskell,memory-management,ghc,Haskell,Memory Management,Ghc,我使用GHC 7.4编译以下函数: nodups' :: [Int] -> Bool nodups' = ok empty where ok _ [] = True ok seen (n:ns) = not (n `member` seen) && ok (n `insert` seen) ns member n word = testBit word n insert n word = setBit word n

我使用GHC 7.4编译以下函数:

nodups' :: [Int] -> Bool
nodups' = ok empty
  where ok _ [] = True
        ok seen (n:ns) = not (n `member` seen) && ok (n `insert` seen) ns
        member n word = testBit word n
        insert n word = setBit word n
        empty = 0 :: Int
函数在小整数列表中查找重复元素。集合
是一组小整数作为位向量的表示。分析器(使用
ghc-prof-auto-all
运行)声称
ok
函数占总分配的22%。查看带有
-ddump siml
的输出,我无法理解为什么要分配此代码。我检查过了,据我所知,它没有为调用
insert
分配thunk

我应该看什么来识别正在分配的代码部分?

通常 我知道函数式语言的简单(科学)实现,如果我没记错的话,Haskell可能会用到

这意味着(如果我没记错的话)您的程序状态被表示为一个“树”,其中节点是(为了简单起见)您在代码中使用的函数。树叶将成为它的论据。然后,“G-Maschine”沿着“Spine”(左侧节点链)查看,并在可用的“函数集”(“超级组合器”)中查找它可以应用的模式匹配。如果从定义的左侧识别出mattern匹配,则将其替换为定义的右侧

这意味着,即使是像

ok seen (n:ns) = not (n `member` seen) && ok (n `insert` seen) ns
甚至

(n:ns) = ns
正在计算机内存中执行某些操作,即匹配模式

       ...
     ...
    (:)
   /   \
  n     ns
并将其替换为

       ...
     ...
    ns
最终结果可能比输入消耗更少的内存,但这是一个动态步骤,因此必须在某个地方进行。如果这是一次又一次的重复(在一个“紧循环”中),那么这将使您的CPU繁忙,也会影响您的内存——仅仅因为G机器正在运行。(正如我所说,我不确定G-Machine的概念是否适用于这里,但我猜它是类似的)

具体猜测
除此之外,我还有一些怀疑
testBit
setBit
看起来像列表上的索引操作。如果是的话,可能需要一些工作。如果它们是合适的数组,就可以了。如果它们是一种地图或集合。。。好。。。可能会涉及代价高昂的散列?或者通过平衡树实现,它使用大量(昂贵的?)比较操作?

如果没有其余的代码,很难判断,但这里有两种可能性<代码>确定
必须为每个元素分配一个新的整数。无固定整数很便宜,但如果您不分配太多其他整数,它们可能会占主导地位。此外,如果参数列表中充满了惰性值,
节点将强制对其求值,这可能导致分配成本归属于此处。您可能想尝试使用
+RTS-hc
或其他内存配置选项之一来获取更详细的信息。我的主要怀疑是,您的列表中充满了惰性值,而
节点会强制执行这些值。尝试
deepseq
在查看列表之前检查一下这是否会减少
nodups'
@DanielFischer我知道那些家伙很懒。但是我想我不明白为什么分配会被计入
nodups'
而不是cons所在的函数。(实际上,其他两个函数是负责分配的函数。)我将不得不再次阅读成本中心的论文。成本分配给了强制评估的函数(至少,过去是这样,Simon M.最近在评测代码中发生了很多变化,可能会发生变化),不一定是产生thunk的函数。
nodups'
的核心尽可能使用unbox
Int#
s(当然是使用
-O2
),因此它本身不会分配太多,除非它确实经常被调用。IIRc使用的是无脊椎无标记的G-machine。有关介绍和如何为其实现编译器,请参阅原始论文。
setBit
testBit
是位操作,
setBit-word n
word |(1
    member n word = testBit word n
    insert n word = setBit word n