52700.fb2
0.2
0.2
seconds
Рис. 10.12: Профиль кучи для утечки памяти
main = print . sum2 . xs . read =<< fmap head getArgs
where xs n = [1 .. 10 ^ n]
sum2 :: [Int] -> (Int, Int)
sum2 = iter (0, 0)
where iter c
[]
= c
iter c
(x:xs) = iter (tick x c) xs
tick :: Int -> (Int, Int) -> (Int, Int)
tick x (! c0, ! c1) | even x
= (c0, c1 + 1)
| otherwise = (c0 + 1, c1)
Мы сделали функцию tick строгой. Теперь посмотрим на профиль:
$ ghc --make leak2.hs -rtsopts -prof -auto-all
$ ./leak2 6 +RTS -K30m -hc
(500000,500000)
170 | Глава 10: Реализация Haskell в GHC
$ hp2ps -e80mm -c leak2.hp
Не получилось (рис. 10.13). Как же так. Посмотрим на расход памяти отдельных функций. tick стала
строгой, но этого не достаточно, потому что в первом аргументе iter накапливаются вызовы tick. Сделаем
iter строгой по первому аргументу:
leak2 6 +RTS -K30m -hc
1,854,625 bytes x seconds
Fri Jun 1 21:38 2012
bytes
12M
10M
(102)main.xs/main/Main.CAF
8M
6M
(101)sum2.iter/sum2/main/M...
4M
2M
0M
0.0
0.0
0.0
0.1
0.1
0.1
0.1
0.1
0.2
0.2