Task.Delay vs. SpinWait.SpinOnce
Is there any performance loss/difference compared between using Task.Delay (allocating multiple task objects? that allocate a internal timer?) vs. SpinWait.SpinOnce?
The specific context I want to take, for example: A loop that receives data from a TCP socket server from clients. I don't necessarily need to save each socket, it just connects, sends (my app as server read the data) and closes the connection.
In this context, would SpinWait be more recommended or even use Task.Delay to control the current task's wait?
And in a context then i need to store these sockets for constantly processing (they will not connect early unless have an error or client ask for disconnection)
18 Replies
SpinOnce is going to block the current thread.
await Task.Delay will release it to do other work.
spin wait is incredibly performance intensive, it's basically a while(true) loop that does nothing
So they're very different.
So I want this to happen, except in the second example, when accepting the connection I start another task to process this connection later.
if you're already in an async environment you should use async delay APIs
wow, I thought it could be lighter
the concept of spin waiting is very primitive, it's really just running a tight loop for a certain amount of time or number of cycles
Why are you doing a wait at all?
What are you waiting for?
it was more like a game server, doing the main loop to accept connections from clients, then processing in another task.
Then I'm afraid of, for example, reaching 200 simultaneous connections and ending up causing problems with excessive memory allocations with tasks.
You can use an async counting semaphore to limit how many connections are actively being processed.
i think you're underestimating how powerful computers are
Tasks are incredibly lightweight in memory, I assume you mean the memory created by whatever work the tasks are doing.
Hmm, I hadn't thought of that. because the strategy I use is to start a task to read/write for each connection. I think it's not the best way to do this, so I was looking for alternative solutions for this
eg: player 1 ( task 1 = read from stream, task 2 = write from queue to stream)
pro tip: don't optimize before there's an actual problem
thanks for the tip 😄
without having something quantifiable to blame for a performance problem premature optimization is more likely to overcomplicate the code and/or waste development time for no benefit or potentially even worse performance
i'm sure mtreit has some benchmarks that demonstrate what looks fast and what is fast aren't necessarily the same thing 😛
It is definitely a good idea to load test your implementation - spin up as many connections as possible and note when it tips over and dies. If you need to actually handle that many concurrent requests, then go optimize it so it doesn't tip over and die. Otherwise just return server too busy or some equivalent.
I'll test doing that. Thank you very much for the tips!