I'm looking for some guidance on the "workload threshold" between where async/await makes sense (e.g. to free up IO Completion Ports and avoid thread starvation) vs. unit of work being too simple/cheap to execute, so synchronous execution is a better choice.
In other words, could the use of async/await lead to degraded performance when used in conjunction with relatively fast/resource-inexpensive units of work, and simply executing the work synchronously would be the preferred approach?
Example (all in one method, all asynchronous with await):
ReadAsStreamAsync
CopyToAsync
FlushAsync
Asynchronous code does introduce a small amount of overhead at run time, but for low traffic situations the performance hit is negligible, while for high traffic situations, the potential performance improvement is substantial.
async functions use an implicit Promise to return results. Even if you don't return a promise explicitly, the async function makes sure that your code is passed through a promise. await blocks the code execution within the async function, of which it ( await statement ) is a part.
The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.
Async/await incurs a significant hit to performance, thanks to the overhead of the state machine. Nearly every article states that async is actually slower than synchronous. Paradoxically, performance is also the selling-feature of async await.
I recommend you approach this not from a timing standpoint, but from an I/O-vs-CPU standpoint.
CPU-bound methods are naturally synchronous; I/O-bound methods are naturally asynchronous.
I'm assuming that your environment is server-side, based on your example:
All of these are naturally-asynchronous operations, so they should all be implemented asynchronously. CPUs are incredibly faster than memory, which is incredibly faster than network or disk I/O. Because of this, if you implement a naturally asynchronous method synchronously, you will block a thread. This isn't the end of the world, but the thread pool has to compensate if it's blocked for too long, and the only time you're "saving" is the thread switch time, which will be orders of magnitude shorter than any network or disk I/O could possibly be.
Another thing to consider is unpredictable latency, which usually happens due to resource contention. What if another process is writing to the db at the same time? What if there's a routing hiccup while the file is uploading, requiring retransmission of packets? What if the disk is defragmenting while you're trying to write the output file? Asynchronous operations have a tendency to be unpredictable like this, and async
code ensures you won't be blocking a thread for much longer than you expected.
In conclusion: use synchronous code for synchronous (CPU-bound) work, and asynchronous code for asynchronous (I/O-bound) work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With