When I run the following test (built with F#2.0) I get OutOfMemoryException. It takes about 5 min to reach exception on my system (i7-920 6gb ram if it was running as x86 proces
I think you're correct - there seems to be a memory leak in the implementation of StartChild
.
I did a bit of profiling (following a fantastic tutorial by Dave Thomas) and the open-source F# release and I think I even know how to fix that. If you look at the implementation of StartChild
, it registers a handler with the current cancellation token of the workflow:
let _reg = ct.Register(
(fun _ ->
match !ctsRef with
| null -> ()
| otherwise -> otherwise.Cancel()), null)
The objects that stay alive in the heap are instances of this registered function. They could be unregistered by calling _reg.Dispose()
, but that never happens in the F# source code. I tried adding _reg.Dispose()
to the functions that get called when the async completes:
(fun res -> _reg.Dispose(); ctsRef := null; resultCell.RegisterResult (Ok res, reuseThread=true))
(fun err -> _reg.Dispose(); ctsRef := null; resultCell.RegisterResult (Error err,reuseThread=true))
(fun err -> _reg.Dispose(); ctsRef := null; resultCell.RegisterResult (Canceled err,reuseThread=true))
... and based on my experiments, this fixes the problem. So, if you want a workaround, you can probably copy all the required code from control.fs
and add this as a fix.
I'll send a bug report to the F# team with a link to your question. If you find something else, you can contact them by sending bug reports to fsbugs
at microsoft
dot com
.