You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm asking here, as StackOverflow didn't tell anything useful, the cause is rather Observable.subscribe than ConcurrentCollection.
I had an operation (submit updates to database) and wanted to record what other events happen during the same time.
So I had a method with a local ConcurrentDictionary and an observable subscribe filling that.
It looks to me that out even if I dispose the observable the collection is not GC-collected. The server did leak memory like 500MB per day, which is not acceptable for a long running server.
After changing the ConcurrentDictionary to a list (with manual locking), the memory leak is gone. But concurrent collections should be the way to go, not manual locking.
I'll try to simulate the issue with a script:
openSystemopenSystem.Collections.Concurrent// Whatever observable stream, I'll took a one from:// https://fsharpforfunandprofit.com/posts/concurrency-reactive/letcreateTimerAndObservable timerInterval =lettimer=new System.Timers.Timer(float timerInterval)
timer.AutoReset <-trueletobservable= timer.Elapsed
lettask=async{
timer.Start()do! Async.Sleep 5000
timer.Stop()}(task,observable)letbasicTimer2,timerEventStream = createTimerAndObservable 1000/// Create local ConcurrentDictionary/// only for listening events at that time/// Then dispose the whole thingletmyFunc()=async{lettmpItems= ConcurrentDictionary<_,_>()use o =
timerEventStream
|> Observable.subscribe (fun x ->letnow= DateTime.Now
printfn "tick %A" now
tmpItems.GetOrAdd(now, x)|> ignore)// Small operation during which I record the eventsdo! Async.Sleep 2000// Disposing should allow tmpItems to be GC-collected after this method exits.
o.Dispose()
tmpItems.Clear()}|> Async.StartAsTask
letstartMem= GC.GetTotalMemory(true);
myFunc()letendMem= GC.GetTotalMemory(true);
Async.RunSynchronously basicTimer2
printfn "Memory usage: %O"(endMem - startMem)
Environment is .NET Framework full 4.7.1, Windows 10.
// FSharp.Core, Version=4.7.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[assembly: AssemblyFileVersion("4.700.19.40208")]
This discussion was converted from issue #10315 on February 06, 2021 22:25.
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I'm asking here, as StackOverflow didn't tell anything useful, the cause is rather
Observable.subscribe
than ConcurrentCollection.I had an operation (submit updates to database) and wanted to record what other events happen during the same time.
So I had a method with a local ConcurrentDictionary and an observable subscribe filling that.
It looks to me that out even if I dispose the observable the collection is not GC-collected. The server did leak memory like 500MB per day, which is not acceptable for a long running server.
After changing the ConcurrentDictionary to a list (with manual locking), the memory leak is gone. But concurrent collections should be the way to go, not manual locking.
I'll try to simulate the issue with a script:
Environment is .NET Framework full 4.7.1, Windows 10.
// FSharp.Core, Version=4.7.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[assembly: AssemblyFileVersion("4.700.19.40208")]
Beta Was this translation helpful? Give feedback.
All reactions