(→See also: Added "Pinpointing space leaks in big programs")
|(3 intermediate revisions by 3 users not shown)|
Latest revision as of 07:00, 13 August 2014
A memory leak means that a program allocates more memory than necessary for its execution. Although Haskell implementations use garbage collectors, programmers must still keep memory management in mind. A garbage collector can reliably prevent dangling pointers, but it is easily possible to produce memory leaks, especially in connection with lazy evaluation. Note that a leak will not only consume more and more memory but it will also slow down the garbage collector considerably! Maybe it is even the reason for the widely spread opinion that garbage collectors are slow or not suited for realtime applications.
 1 Types of leaks
 1.1 Holding a reference for a too long time
Consider for example:
let xs = [1..1000000::Integer] in sum xs * product xs
To achieve this while avoiding code duplication, we can turn the list definition into a function with a dummy argument.
let makeXs n = [1..n::Integer] in sum (makeXs 1000000) * product (makeXs 1000000)
 1.2 Building up unevaluated expressions
Another typical cause of memory leaks are unevaluated expressions,the classical example being to sum up the numbers of a list (known as
foldl (+) 0 [1..1000000::Integer]
The problem is, that the runtime system does not know, whether the intermediate sums are actually needed at a later point, and thus it leaves them unevaluated.I.e. it stores something equivalent to
foldl' (+) 0 [1..1000000::Integer]
 1.3 Keeping not needed references alive
Consider the following definition:
x = fst (a, b)
 2 Detection of memory leaks
A memory leak can be detected by writing a test that should require only a limitted amount of memory and then run the compiled program with restricted heap size. E.g. you can restrict the heap size to 4 MB like in this example:
$ ./mytest +RTS -M4m -RTS
 3 A note on GHCi
If you are noticing a space leak while running your code within GHCi, please note that interpreted code behaves differently from compiled code: even when using `seq`.
Consider starting ghci as follows:
$ ghci -fobject-code
For this, see Compiling to object code inside GHCi.
 4 See also
- Chasing a Space Leak in Shake on Neil Mitchell's Haskell Blog (2013-02-25)
- Blog post "Anatomy of a thunk leak"
- Blog post "Space leak zoo"
- Haskell Cafe on a space leak caused by the garbage collector that did not recognize a selector-like function call
- Haskell libraries on Make lines stricter to fix a space leak
- Blog post Pinpointing space leaks in big programs