Gustavo Piucco
Gustavo Piucco

Reputation: 557

C# Socket performance with .Net 4.5 Async vs [...]Async vs Begin[...]

Currently, from what I've researched, there are 3 ways to work with socket asynchronously:

.Net 4.5 Async example: Using .Net 4.5 Async Feature for Socket Programming (second post)

[...]Async: http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx

Begin[...]: http://msdn.microsoft.com/en-us/library/5w7b7x5f(v=vs.110).aspx

I am very confused with all the options .Net provides for working with asynchronous sockets. Why should I use one or the other? What better choice to have performance with thousands of simultaneous connections?

Upvotes: 6

Views: 8113

Answers (4)

noseratio
noseratio

Reputation: 61744

What better choice to have performance with thousands of simultaneous connections?
...
A curiosity regarding the Begin[...]. If I have a MMORPG server where one connection interacting with each other for position update, animation, effects (basic MMORPG mechanism), in numbers, which would be "heavily loaded servers"? 200~300 simultaneous connections?

On the server side, you may benefit equally well from using any asynchronous socket APIs, either Begin/End-style APM ones, event-based EAP ones or Task-based TAP ones. That's because you'll be blocking fewer threads, as opposed to using the synchronous APIs. So, more thread will be available to concurrently serve other incoming requests to your server, thus increasing its scalability.

Most likely, your won't see any performance advantage of using TAP socket APIs over their APM or EAP analogues. However, the TAP API pattern is so much easier to develop with than APM or EAP. When used with async/await, it produces shorter, more readable and less error-prone code. You get natural pseudo-linear code flow, which is not otherwise possible with APM callbacks or EAP event handlers. If you're unable find a proper Task-based socket API, you can always make one yourself from a Begin/End APM API with Task.FromAsync (or from an EAP API, check "A reusable pattern to convert event into task").

When it comes to a client side UI app, the scalability is not that important, but there's another benefit from the TAP pattern. With little efforts, it helps making your UI responsive, because you won't be blocking the UI thread (what usually happens while waiting for the result of a synchronous call). This is not specific to Task-based Socket API, it applies to any Task-based API, e.g, Task.Delay() or Stream.ReadAsync().

For some good reading materials on asynchronous programming in C#, check the async/await tag wiki:

https://stackoverflow.com/tags/async-await/info

Upvotes: 7

cost
cost

Reputation: 4490

First, you might want to check out this article on MSDN about what the differences between the various async programming mechanisms in .NET are.

Begin[…] was the first async socket implementation, using APM (Asynchronous Programming Model). It takes a callback as one of its arguments. While somewhat dated compared to newer methods, this works fine if you don't mind dealing with callbacks and the messy code they can create. There's also some extra overhead associated with this because of the state object, and on heavily loaded servers this can start to become a problem.

[…]Async uses the newer event based model, and is also a lighter implementation to help deal with the high traffic issues Begin[…] has. This way works nicely, but can also result in messy code if you aren't careful. Oh yea, there's a bug you can read about here, though it's likely something you won't care about unless you're building a very performant piece of software.

Task based asynchronous programming (TPL) is the newest mechanism and, with the help of the async/await keywords, can have most (if not all) of the efficiency associated with […]Async while offering much easier to understand code. Also, with Tasks, it's much easier to wait on multiple operations to finish at a time. It's important note that, while there are several native .NET functions that implement TPL and return a Task, there isn't yet one for Socket operations. There are examples of how to do this online, but it requires a bit of extra work.

Upvotes: 1

Cory Nelson
Cory Nelson

Reputation: 30021

Methods using SocketAsyncEventArgs most closely match the underlying Windows technology (I/O Completion Ports). They are essentially a bare-metal wrapper designed to perform zero allocation and extract the highest performance at the cost of a less friendly API. This has a disadvantage of more tightly coupled code as it doesn't implement any standard Stream API. The other async socket methods all wrap this one.

Methods using a Begin/End pair are using what's called the Asynchronous Programming Model (APM). APM is the original async model of .NET. It's very easy to write spaghetti code if you use it half-cocked, but it's functional and fairly simple to use once you have some experience with it. They shouldn't see much use in modern .NET, though, because we've got something far easier and better performing:

Methods returning a Task are using the Task-based Asynchronous Pattern (TAP). Tasks are a pure upgrade to APM: they're more flexible, easier to compose, and should generally have equal or better performance. When combined with language-integrated async/await, you can write code that performs great and is significantly easier to understand and maintain.

tl;dr use Task methods, unless you've got a requirement of extreme perf. Then use SocketAsyncEventArgs methods. Don't use APM methods.

Upvotes: 10

vtortola
vtortola

Reputation: 35965

If you have the chance of using .NET 4.5 and async/await, I totally recommend it.

Basically there are these ways of doing multithreading in .NET:

  1. Thread.
  2. ThreadPool.QueueWorkItem.
  3. XXXAsync method and the XXXCompleted event.
  4. BeginXXX and EndXXX methods.
  5. Task Parallel Library.
  6. async/await

The first one are raw threads, an option you should avoid because creating threads is a expensive operation. The rest, are just different ways of using the ThreadPool, that is a tool responsible of maintain a collection of threads that can be used to schedule your tasks, yielding a better performance than the first option.

The use different syntax's, but at to me, the most clear is async/await. I have created recently a WebSocket connector using sockets and asyn/await and the performance is quite good. Technically, async/await are not giving you a performance boost, but the clarity in the code will allow you to streamline the approach of your application, and that may give a good performance boost in comparison with a messy code based on continuations.

Upvotes: 1

Related Questions