Ticket #917 (new bug)
-O introduces space leak
| Reported by: | claus.reinke@… | Owned by: | |
|---|---|---|---|
| Priority: | lowest | Milestone: | _|_ |
| Component: | Compiler | Version: | 6.5 |
| Keywords: | Cc: | prokhorenkov@…, pho@…, mail@…, ezyang@… | |
| Operating System: | Unknown/Multiple | Architecture: | Unknown/Multiple |
| Type of failure: | None/Unknown | Difficulty: | Unknown |
| Test Case: | Blocked By: | ||
| Blocking: | Related Tickets: |
Description
consider the following variant of a popular space problem
initlast :: (()->[a]) -> ([a], a)
initlast xs = (init (xs ()), last (xs ()))
main = print $ case initlast (\()->[0..1000000000]) of
(init, last) -> (length init, last)
the long list has been wrapped in abstractions to avoid sharing, gaining constant space processing rather than the space leak in the original code - see
http://www.haskell.org/pipermail/haskell-cafe/2006-September/018447.html
http://www.haskell.org/pipermail/haskell-cafe/2006-September/018464.html
this works nicely if compiled without -O, but unfortunately, -O reintroduces the space leak (apparently lifting and sharing the common and space-expensive subexpression).
1. I didn't see a ticket for this issue, so I wanted to record the example
2. avoiding sharing isn't always possible, so it would be nice if one could "bypass" sharing in such cases. in the old g-machine, that might have been as simple as introducing a pragma that tells the compiler to omit the update after the eval in the code for some subexpression (so the original application node would not be overwritten by the space-expensive result, trading time for space). is there a chance for a similar trick in GHC? so one might write code like this (handwaving:-):
initlast :: [a] -> ([a], a)
initlast xs = (init ({-# COPY #-} xs), last ({-# COPY #-} xs))
main = print $ case initlast [0..1000000000] of
(init, last) -> (length init, last)
