Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

The other thing I noticed is that they are wrapping every Task.Delay(…) inside a Task.Run(…) call. That should not be necessary. The inner task will yield back to the called when it hits the delay call anyway. There is no need to queue it with an immediate yield as if it is background or cpu-bound work.

The Run() call might be creating a more complex state machine and using more memory than necessary (2 tasks vs just 1 for each delay). The memory usage might be even lower if the Run() call is dropped.



view as:

Yup - this would do the job faster and better.

Task task = Task.Delay(TimeSpan.FromSeconds(1)); tasks.Add(task);


I was sufficiently curious and just went and tested this using BenchmarkDotNet. The example code is here (https://github.com/J-Bax/CSharpBenchmarkExamples).

The difference is quite significant.

(1) With the authors code (using Task.Run), I get ~428MB of allocations.

(2) Dropping the unnecessary Task.Run(...), I get ~183MB of allocations.

(3) Doing (2) and waiting N times on the same delay, I get ~39MB of allocations.

This was all using .NET 6 too. .NET 7 or the 8 preview might be even better since they are working hard on performance in recent releases.

So even looking at just (2), that puts .NET on par with the rust library.


Legal | privacy