在这个程序中:
select()
(编译并使用module Main where
import Data.IntSet
main = do
print $ size
$ {-# SCC "fromAscList" #-} fromAscList
$ {-# SCC "generate_list" #-} [1..1000]
运行)
我从GHC分析器获得此输出(为简洁起见编辑):
stack ghc Main.hs -- -prof -fprof-auto && ./Main +RTS -p
这似乎表明 total alloc = 202,704 bytes (excludes profiling overheads)
COST CENTRE MODULE SRC %time %alloc
generate_list Main Main.hs:6:40-48 0.0 39.5
fromAscList Main Main.hs:(5,38)-(6,48) 0.0 36.2
main Main Main.hs:(3,1)-(6,48) 0.0 5.0
individual inherited
COST CENTRE MODULE %time %alloc %time %alloc
main Main 0.0 0.1 0.0 75.8
fromAscList Main 0.0 36.2 0.0 75.7
generate_list Main 0.0 39.5 0.0 39.5
在程序过程中分配80Kb(202,704字节的39.5%),然后[1..a']
再次分配相同的数量。 (输入Int的一个分配,以及存储的Int的另一个分配?)
两个问题:
fromAscList
的分配,还是会重复使用同一块内存? (我想知道堆分配是否可能成为瓶颈。)generate_list
?答案 0 :(得分:2)
您应该使用fromDistinctAscList
,否则必须将每个下一个Int
与其前任进行比较,以确定是添加还是跳过,这必然会产生您观察到的开销。 (虽然我没有查看源代码,但似乎有理由猜测会发生这种情况,在这种情况下我们很难期望以最佳方式分配内存。)
试试这段代码:
main = do
print $ size
$ {-# SCC "fromDistinctAscList" #-} fromDistinctAscList
$ {-# SCC "generate_list" #-} [1..1000]
我观察到的表现是记忆力提高了36%。 (这个数字似乎与你的一致。)以下是分析报告的相关部分:
COST CENTRE MODULE SRC no. entries %time %alloc %time %alloc
....
main ListAlloc ListAlloc.hs:(5,1)-(8,55) 276 1 0.0 0.2 0.0 62.5
fromDistinctAscList ListAlloc ListAlloc.hs:(7,46)-(8,55) 278 1 0.0 1.1 0.0 62.4
generate_list ListAlloc ListAlloc.hs:8:40-55 279 1 0.0 61.2 0.0 61.2
...
关于分配的实际情况,我不确定我是否理解这个问题,但是,查看带有+RTS -S
的垃圾收集,两种变体一直在几乎相同的内存中运行,由于增长而线性增长IntMap
。似乎所有其他计算都是在相当小的常量内存中完成的。