|
|
|
|
|
by neonsunset
572 days ago
|
|
Indeed, looping over a Task.Delay likely causes a lot of churn in timer queues - that's 10M timers allocated and scheduled! If it is replaced with 'PeriodicTimer', the end result becomes more reasonable. This (AOT-compiled) F# implementation peaks at 566 MB with WKS GC and 509 MB with SRV GC: open System
open System.Threading
open System.Threading.Tasks
let argv = Environment.GetCommandLineArgs()
[1..int argv[1]]
|> Seq.map (fun _ ->
task {
let timer = PeriodicTimer(TimeSpan.FromSeconds 1.0)
let mutable count = 10
while! timer.WaitForNextTickAsync() do
count <- count - 1
if count = 0 then timer.Dispose()
} :> Task)
|> Task.WaitAll
To Go's credit, it remains at consistent 2.53 GB and consumes quite a bit less CPU.We're really spoiled with choice these days in compiled languages. It takes 1M coroutines to push the runtime and even at 100k the impact is easily tolerable, which is far more than regular applications would see. At 100K .NET consumes ~57 MB and Go consumes ~264 MB (and wins at CPU by up to 2x). |
|