2

Is it better to not use any Async methods (CopyToAsync, ReadAsync, etc...) if I know that the stream I'm operating on is a MemoryStream ?

A comment of Stephen Clearly on this SO question made me doubt on the approach I'm using in a server-application that should be able to handle many concurrent requests.

In that application, all I/O is done async so that no threads are wasted. However, as it seems that CopyToAsync f.i. is not really asynchronous on a MemoryStream, I wonder if I have any benefit -even in a server-application- to use async operations on a MemoryStream.

Frederik Gheysels
  • 56,135
  • 11
  • 101
  • 154
  • 3
    `MemoryStream` is a smell when you're going for performance at all, as it implies memory is being allocated and copied around, typically unnecessarily. However, there's no need to special-case it when you *are* using it if the code is already `async` throughout -- having a bunch of `if (stream is MemoryStream)` checks is almost certainly not going to improve actual performance, as opposed to eliminating the memory streams altogether. YMMV, of course, and profiling should tell you more. – Jeroen Mostert Nov 14 '17 at 08:43
  • I already profiled, and using async is slower than using straight sync. I initially thought that using async, the application would be able to perform better under heavy load, but since async io to a memorystream is not really async, all we do is add unnecessary overhead. So I wonder what 's the gain of using CopyToAsync on mem-streams – Frederik Gheysels Nov 14 '17 at 09:48
  • If you copy from Memory stream to memory stream there is nothing to be gained. It just uses write and returns a completed [task](https://referencesource.microsoft.com/#mscorlib/system/io/memorystream.cs,1a4dcb744a23ba6f). – Filip Cordas Nov 14 '17 at 10:32
  • 2
    Async code is *never* faster than sync code. But it is possible to get more work done when a threadpool thread is not occupied with waiting. You need a very different kind of test to see this, it has to measure through-put and not code execution speed and it is important that the machine is loaded sufficiently so those tp threads can be put to a good use. Inevitably a memory stream is going to be slower since it doesn't free up a thread. You perhaps ought to fret a bit about seeing a measurable perf loss, just keep in mind that anything less than 15% is not statistically significant. – Hans Passant Nov 14 '17 at 10:41
  • @HansPassant I knew it was going to be slower and I know what I can gain with async code, but since async is 'faked' on MemStreams, I wonder if there is anything to gain in that case ? – Frederik Gheysels Nov 14 '17 at 10:51
  • Yes, yes, we know what you are fretting about already. But you are not posting anything that will help us help you to stop fretting about it. Do the load test, post the results you got. If you don't have the time to do the test properly but do have time to change working code then it gets hard to post anything helpful. Just do it and you'll feel better. – Hans Passant Nov 14 '17 at 10:56

1 Answers1

8

Well, if you check MemoryStream implementation, you'll find that ReadAsync (and WriteAsync) are actually sync without using any additional threads. And while there is some overhead, it's pretty small and should be negligible.

CopyToAsync is a different beast. While other async methods works only on one thread, CopyToAsync works on two. And while your source MemoryStream doesn't benefit from async, destination thread can. Of course, if both streams are memory streams you won't get any benefit at all.

So, answering your question in general, MemoryStream have async methods only for consistency with other stream implementations. But you won't get any significant performance degradation when you are using it.

P.S. If you need good performance with MemoryStream, it is better avoid re-allocations, re-use underlying buffers, etc. But it's different topic unrelated to async.

arbiter
  • 9,447
  • 1
  • 32
  • 43