Does Async.StartChild have a memory leak?

后端 未结 1 871
甜味超标
甜味超标 2021-02-19 01:19

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

相关标签:
1条回答
  • 2021-02-19 01:41

    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.

    0 讨论(0)
提交回复
热议问题