Space leak
also: thunk, thunk leak, laziness leak
Memory a program holds longer than it needs to. In a lazy language the usual cause is a chain of unevaluated thunks: a lazy left fold over a list builds one suspended addition per element and only performs them at the end. A heap profile by closure type shows it as a growing THUNK band.
A space leak is not a leak in the C sense: the memory is reachable and will be freed eventually. The program is still wrong about how much it keeps, and the difference can be the whole input.
Haskell. The lazy foldl builds a thunk per element before adding any of them; foldl' forces the accumulator at each step.
import Data.List (foldl')leaky = foldl (+) 0 [1 .. 10000000 :: Int]steady = foldl' (+) 0 [1 .. 10000000 :: Int]
The other common cause is retention: sum xs / fromIntegral (length xs) traverses xs twice, so the whole list has to be kept between the two traversals even if it was produced lazily. Computing both in one fold lets each cell be collected as soon as it is read.
Heap profiling finds both. GHC's +RTS -hT breaks the live heap down by closure type, and a leak of suspended work shows up as a THUNK band that grows over the run instead of staying flat.
see also
- Tail callA call whose result is returned directly, with nothing left for the caller to do. The caller's frame can be reused for it, so a loop written as tail recursion runs in constant stack space. OCaml guarantees this, and the [@tailcall] attribute makes the compiler warn when a call marked with it is not one.
- Generational GCA garbage collector that splits the heap by age, because most objects die young: new objects go to a small nursery collected often by copying, and survivors are promoted to a larger heap collected rarely. A write barrier records old-to-young pointers so that a minor collection need not scan the old heap.
referenced by
further reading
- P. Wadler, “Fixing some space leaks with a garbage collector”, Software: Practice and Experience 17 (1987).
- C. Runciman, D. Wakeling, “Heap profiling of lazy functional programs”, Journal of Functional Programming 3 (1993).