Ticket #2186 (closed bug: invalid)

Opened 5 years ago

Last modified 5 years ago

unsafePerformIO prevents space leak?

Reported by: ravi Owned by:
Priority: lowest Milestone: 6.8.3
Component: Compiler Version: 6.8.2
Keywords: Cc:
Operating System: Linux Architecture: Unknown/Multiple
Type of failure: Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

Sadly, I don't have a concrete testcase for this, but I've fixed this issue in the Bluespec compiler more than once, so I have a strong suspicion that there's a GHC bug (or lack of optimization) going on here.

The basic situation is that I have a deeply nested structures of IORefs (I once measured one particular instance as including chains over 300 IORefs deep). I want to walk this structure recursively (it does not contain loops) without mutating it to compute a property of this structure. Generally speaking I'm either looking to accumulate certain kinds of nodes or I'm looking to detect the presence or absence of a certain kind of node.

If I traverse this structure in the IO monad (using readIORef directly and recursing and combining using things like mapM and foldM) I see a huge space leak (which can be confirmed with profiling). If I take the same traversal and wrap up the readIORef inside an unsafePerformIO (and change mapM to map and the like) the space leak disappears. This surprised me because I thought it would be the sort of thing GHC could figure out.

I'm sorry I can't easily give you a testcase, but I hope I've included enough detail that you have a fighting chance of reproducing it. Please let me know if you have any questions.

Change History

Changed 5 years ago by tim

Have you tried compiling the monadic version with -fno-state-hack? See http://www.haskell.org/ghc/docs/latest/html/users_guide/options-optimise.html

It's not a solution, but it would be interesting to know what happens if you try that.

Changed 5 years ago by igloo

  • difficulty set to Unknown

I'm not sure I follow. If you do something like

do bools <- mapM readIORef refs
   return (and bools)

then all the Bools will need to be in memory at once, as all the readIORefs will be run before mapM returns, whereas

and (map (unsafePerformIO . readIORef) refs)

would run in constant space. Have I misunderstood the problem?

Changed 5 years ago by igloo

  • milestone set to 6.8.3

Changed 5 years ago by igloo

  • priority changed from normal to lowest

(waiting for response)

Changed 5 years ago by igloo

  • status changed from new to closed
  • resolution set to invalid

Please reopen if you still think there's a bug in here.

Changed 5 years ago by simonmar

  • architecture changed from Multiple to Unknown/Multiple
Note: See TracTickets for help on using tickets.