我一直在编写一个直方图,这里的大家提供了很好的帮助。我使用哈希表来存储键和频率值,因为键的分布是未知的;所以它们可能没有被排序或连续地放在一起。
我的代码问题在于它花费了太多时间在GC上,看起来像是空间泄漏,因为GC的时间占了60.3% - 所以我的生产力只有39.7%。
出了什么问题?我尝试在直方图函数中使事情变得更加严格,并将其内联(GC时间从69.1%降至59.4%)。
请注意,我通过不更新HT中的频率来简化了此代码。
我的代码问题在于它花费了太多时间在GC上,看起来像是空间泄漏,因为GC的时间占了60.3% - 所以我的生产力只有39.7%。
出了什么问题?我尝试在直方图函数中使事情变得更加严格,并将其内联(GC时间从69.1%降至59.4%)。
请注意,我通过不更新HT中的频率来简化了此代码。
{-# LANGUAGE BangPatterns #-}
import qualified Data.HashTable.IO as H
import qualified Data.Vector as V
type HashTable k v = H.BasicHashTable k v
n :: Int
n = 5000000
kv :: V.Vector (Int,Int)
kv = V.zip k v
where
k = V.generate n (\i -> i `mod` 10)
v = V.generate n (\i -> 1)
histogram :: V.Vector (Int,Int) -> Int -> IO (H.CuckooHashTable Int Int)
histogram vec !n = do
ht <- H.newSized n
go ht (n-1)
where
go ht = go'
where
go' (-1) = return ht
go' !i = do
let (k,v) = vec V.! i
H.insert ht k v
go' (i-1)
{-# INLINE histogram #-}
main :: IO ()
main = do
ht <- histogram kv n
putStrLn "done"
以下是编译的步骤:
ghc --make -O3 -fllvm -rtsopts histogram.hs
诊断:
jap@devbox:~/dev$ ./histogram +RTS -sstderr
done
863,187,472 bytes allocated in the heap
708,960,048 bytes copied during GC
410,476,592 bytes maximum residency (5 sample(s))
4,791,736 bytes maximum slop
613 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 1284 colls, 0 par 0.46s 0.46s 0.0004s 0.0322s
Gen 1 5 colls, 0 par 0.36s 0.36s 0.0730s 0.2053s
INIT time 0.00s ( 0.00s elapsed)
MUT time 0.51s ( 0.50s elapsed)
GC time 0.82s ( 0.82s elapsed)
EXIT time 0.03s ( 0.04s elapsed)
Total time 1.36s ( 1.36s elapsed)
%GC time 60.3% (60.4% elapsed)
Alloc rate 1,708,131,822 bytes per MUT second
Productivity 39.7% of total user, 39.7% of total elapsed
H.insert
有时会增加哈希表的大小,这将调用newSizedReal
,它创建了两个新的MutableArray
,可能会让旧的MutableArray
被垃圾回收。堆分析显示,newSizedReal
确实分配了大量内存。我不知道解决方案是什么,但我怀疑不使用哈希表可能是一个解决办法。 - user2407038fromList
зӨәдҫӢз»ҷдәҶжҲ‘дёҖдёӘжғіжі•гҖӮжҲ‘е°қиҜ•дҪҝз”Ёkv = V.fromList (zip (take n $ cycle [1..10]) (repeat 1))
жқҘз”ҹжҲҗеҗ‘йҮҸпјҢиҖҢдёҚжҳҜдҪҝз”Ёgenerate
гҖӮиҝҷеңЁжҲ‘зҡ„жңәеҷЁдёҠе°ҶGCж—¶й—ҙеҮҸе°‘дәҶ30%гҖӮжүҖд»ҘжҲ‘зҢңй—®йўҳеҮәеңЁеҗ‘йҮҸдёҠпјҢиҖҢдёҚжҳҜе“ҲеёҢиЎЁдёҠгҖӮ - user2407038histogram = accumArray (+) 0 (1, 10) (zip (take n $ cycle [1..10]) (take n $ repeat 1))
。比哈希表快得多,垃圾回收时间也更短。它需要预先知道数据范围,但这应该是一个简单的计算。 - user2407038