C
C#•4mo ago
nathan

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
mtreit
mtreit•4mo ago
SpinOnce is going to block the current thread. await Task.Delay will release it to do other work.
Jimmacle
Jimmacle•4mo ago
spin wait is incredibly performance intensive, it's basically a while(true) loop that does nothing
mtreit
mtreit•4mo ago
So they're very different.
nathan
nathan•4mo ago
So I want this to happen, except in the second example, when accepting the connection I start another task to process this connection later.
Jimmacle
Jimmacle•4mo ago
if you're already in an async environment you should use async delay APIs
nathan
nathan•4mo ago
wow, I thought it could be lighter
Jimmacle
Jimmacle•4mo ago
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
mtreit
mtreit•4mo ago
Why are you doing a wait at all? What are you waiting for?
nathan
nathan•4mo ago
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.
mtreit
mtreit•4mo ago
You can use an async counting semaphore to limit how many connections are actively being processed.
Jimmacle
Jimmacle•4mo ago
i think you're underestimating how powerful computers are
mtreit
mtreit•4mo ago
Tasks are incredibly lightweight in memory, I assume you mean the memory created by whatever work the tasks are doing.
nathan
nathan•4mo ago
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)
Jimmacle
Jimmacle•4mo ago
pro tip: don't optimize before there's an actual problem
nathan
nathan•4mo ago
thanks for the tip 😄
Jimmacle
Jimmacle•4mo ago
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 😛
mtreit
mtreit•4mo ago
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.
nathan
nathan•4mo ago
I'll test doing that. Thank you very much for the tips!