I discovered a memory leak in
Async.StartChild
and here discuss a workaround based on a Future abstraction.
I noticed what appears to be a memory leak in F# standard library
function Async.StartChild
. This happened in a context of
a socket server, where I attempted to perform socket reading and
writing in parallel. It seems that memory use slowly grows and memory
profiler points to some CancellationTokenSource
-related
objects not being released.
As a non-leaking alternative, I used my own abstractions. The basic
idea is to use synchronizable events. Unfortunately Event
is already used in F# to mean something different, so I will use the
word Future
instead. If you know F# events, the key
problem is that subscribing to events after they happen is
meaningless, for example this code procuces nothing:
let test () = let e = Event<_>() e.Trigger(1) e.Publish.Add(printf "%i")
In contrast, Future
objects retain the value. For
simplicity, I allow subscribing and triggering only once. In
addition, the sample includes Executor
code. I found by
experimentation that running short-lived coordination tasks on a
single thread instead of the ThreadPool
is
beneficial. Enjoy:
Why not use Lazy?
ReplyDeleteCan you give an example how you would do that? My understanding is that you can indeed use Lazy for coordination: forcing a Lazy value will make the consumer thread wait until the producer thread will compute the value. The reason this does not make me happy is because it consumes a whole .NET-level thread. With a callback-based Future, only Async-level thread is waiting, which consumes a lot less resources.
ReplyDelete