3 ms·
Tasks specifically allow to never worry about the kind of race conditions you get with WaitGroups and channels for unary cases - after all, you `await` the resu
by neonsunset 2y ago
Tasks specifically allow to never worry about the kind of race conditions you get with WaitGroups and channels for unary cases - after all, you `await` the result immediately, or later on, and even if you do it multiple times with a Task<T>, it is foolproof and will not allow you to make a synchronization mistake because there is no synchronization to do by the user.
They are also cheaper than Goroutines if that's what you want to say: https://gist-github-com.translate.goog/neon-sunset/8fcc31d6853ebcde3b45dc7a2af32127?_x_tr_sl=uk&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp#tldr https://gist-github-com.translate.goog/neon-sunset/8fcc31d68...
In addition, all meaningfully cancellable operations accept 'CancellationToken' which is way easier than goroutine context passing, some overloads also accept timeout instead if that's expected to be the main use of that.
You could make a case about preference for different language syntax and expressiveness, different quality of an SDK from a particular vendor, but the technical arguments made here just do not correspond to reality.
- devjab 2y agoYou're not really making a lot of argumentation to back up your claims. Anyone can Search engine benchmarking and get the results they want. Just look here: https://karl-pickett.medium.com/benchmarking-a-toy-c-task-vs-a-go-goroutine-is-there-any-difference-248f73f7f7b7 https://karl-pickett.medium.com/benchmarking-a-toy-c-task-vs... Hell, you can even test things yourself: https://go.dev/src/runtime/stack.go https://go.dev/src/runtime/stack.go For our specific use case C#'s TPL was ok, but it comes with a massive overhead compared to Goroutines. We can have tens of thousands concurrent threads running at the same time at very little CPU usage (which is primarily what we pay for). It’s not that you can’t use async/await tasks to do the same, but they use a lot more CPU and as such is less cost effective for us. As far as blocking and having meaningful (again meaningful is the keyword) cancellation I encourage you to look to Microsoft and understand the limitations outlined by them in the learning articles starting here: https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/ https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous...
- neonsunset 2y ago> You're not really making a lot of argumentation to back up your claims. Anyone can Search engine benchmarking and get the results they want. This is only possible if you completely ignored the text in my comment and never used C# and Go concurrency primitives side-by-side to evaluate them on their merits. The race conditions risks in Go are very real and so are issues w.r.t closing channels, passing nils, etc. The __much higher___ cost of spawning channels and gorotines is equally as real and you can measure it yourself. Both are intended to be spawned for longer than shortlived scenarios. But even then, you will run out of memory much faster if you have thousands of goroutines waiting on a timer channel versus tasks waiting on PeriodicTimer. This does not make either choice strictly better than the other as both have their tradeoffs but tradeoffs nonetheless that must be acknowledged (like pros and cons of implicit suspend, stackless vs stackful, etc.). You can also take the data from the code snippets from the gist I linked and replicate it with current versions of Go and .NET on your own machine. This is the perfect case that illustrates how much memory consumption you will see with massive amounts of mostly-suspended-periodically-calling-a-service Tasks and Goroutines. But you did not and have a history of constructing arguments in bad faith, not actually discussing strengths and weaknesses of a particular language. Not sure what is the purpose of the link for tasks (which does not talk about cancellation, this one does: [1]) and Go's stack implementation. I'm very well aware of both, which is the driving reason to respond here to salvage the discussion with otherwise wrong claims. Lastly, the data from 2019 is irrelevant because it uses completely different threadpool implementation and is likely measuring also the one-time cost of JIT compilation for code. .NET has significantly evolved since then and provides much better native compilation[2][3] than Go today, as well as much higher throughput[3][4] code w.r.t GC and JIT for long-running services. [1]: https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-cancellation https://learn.microsoft.com/en-us/dotnet/standard/parallel-p... [2]: https://news.ycombinator.com/item?id=41234851 https://news.ycombinator.com/item?id=41234851 [3]: https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/go-csharpaot.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/... (not listed there but if you compile any of the submissions, .NET tends to produce binaries twice as small as Go ones) [4]: https://gist.github.com/neon-sunset/72e6aa57c6a4c5eb0e2711e11f4f31cf?permalink_comment_id=5151443#gistcomment-5151443 https://gist.github.com/neon-sunset/72e6aa57c6a4c5eb0e2711e1... [5]: https://gist.github.com/neon-sunset/c6c35230e75c89a8f6592cacbbd636ee https://gist.github.com/neon-sunset/c6c35230e75c89a8f6592cac...