Re:Memory usage of a toy C# server and client with 500K conc...
by davidgrenier on Sunday January 27, 2019 @04:32AM
(#19011067)
If I may, I'd like to invite you or someone on your team to read a couple of chapters of John Reppy's Concurrent Programming in ML and try Vesa's excellent delivery in https://github.com/Hopac/Hopac.
I'm not clear if you absolutely have to use TPL but CML is likely just a better model for tackling concurrency and Hopac is orders of magnitude more efficient than F#'s async.
Re:Memory usage of a toy C# server and client with 500K conc...
by sparkie on Saturday January 26, 2019 @05:47PM
(#19009054)
There's a `task {}` computation expression is the FSharpx.Extras library, which makes it much more pleasant to work with TPL libraries, and removes the performance issues associated with using Async.AwaitTask etc.
Re:Memory usage of a toy C# server and client with 500K conc...
by strmpnk on Saturday January 26, 2019 @05:52PM
(#19009092)
Yes. That one works pretty well, though it still lags a bit behind the efficient state machines that C# generates which can also help avoid a lot of allocations and indirection in deep task chains. One step at a time though, it'd be great to see F# get a refresh around the TPL (even though it had Async first, it'd be better to align with the platform in the long run).
Re:Memory usage of a toy C# server and client with 500K conc...
by platz on Sunday January 27, 2019 @12:37PM
(#19012726)
This is the most current one https://github.com/rspeele/TaskBuilder.fs that Giraffe also uses.
Re:Memory usage of a toy C# server and client with 500K conc...
by akra on Sunday January 27, 2019 @09:44PM
(#19015068)
The developers I've encountered that use F#'s Async get confused at first mainly because they are used to C#'s Tasks being started upon creation. I personally think the F#'s model conceptually is better and I've seen more surprises with the C# one from dev's I've worked with (e.g. which SynchronizationContext is set and why does it work in my test but not in the app, why is there no trampolining and I'm deadlocking here, why do I need to pass around CancellationTokens everywhere, etc). There are benefits to the F# async model (execution) such as implicit cancellation token parsing from the root task which is much harder to implement if the Tasks are already started before you finish the root, that they are re-runnable, they can run on whatever context you want easier at the composed root level, and the fact that it uses a more generic feature in the language (which usually comes with a slight performance overhead). Both F#'s Async's and Tasks aren't the best for CPU parallelism IMO anyway - my impression is that they are for using up idle IO time across a number of threads more efficiently. An article which I think compares the two despite it being biased a little to F# rightly or wrongly: http://tomasp.net/blog/async-csharp-differences.aspx/
Part of it is not necessarily the design F# took but that the TPL is incompatible enough that the mixing of TPL-centric .Net libraries becomes a problem. It might be wise for F# to support the TPL via computation expressions with something like `task { ... }` (there are a few implementations out there but a compiler supported state machine generator would be more ideal).