Disappointing .Net Sockets article in MSDN Magazine this month

| 13 Comments

The title of the piece is "Get Closer to the Wire with High-Performance Sockets in .NET" which nicely over-hypes the content. How, exactly, am I getting closer to the wire by placing a managed layer between my code and the wire? The summary box is a little more honest; describing the article as covering "basic socket programming" and "factors in creating socket-based servers" which it does...

We start with a basic intro to sockets, moves swiftly to a thread per connection server which is swiftly put to bed due to the lack of scalability of such a design. That's all well and good but the reasons given for the lack of scalability are the number of threads created and destroyed and the amount of memory taken up by each thread. No mention of the horrendous thrashing that you'd experience with 1000 threads all servicing clients. I'd have preferred to have seen a mention of this as otherwise the inexperienced might think that they can simply throw more memory at the problem.

Next we're on to using select which is, rightly, dismissed as being inefficient and prone to starving connections unless you're careful...

Finally we move on to a simple asynchronous IO server which is described as removing the number of connections limit of the thread per connection server and beating the performance of the select based server. Which, I guess, is true. But then comes the bombshell. It's still not that scalable... The best the author can get is 4 times the number of connections than the thread per connection server (and he doesn't specifically say that this is with the async server rather than the select server, but I hope it is...).

So because we "Get Closer to the Wire with High-Performance Sockets in .NET" we can handle, at best, 4000 incoming connections... I'm sorry but I do hope this is a limitation of the author or his hardware rather than the .Net runtime because I just ran up one of my simple C++ servers and established 30775 connections to it; and I'd file that in the "without trying" cabinet as there are several tricks that you can use to reduce the amount of non-paged pool that you use per active connection and, since it was a simple test, I wasn't bothering with any of them. Of course this isn't a fair comparison as I don't have a clue how the author tested his server, and I have no way of knowing how much memory he had in the box (the amount of memory affects the amount of non-paged pool, and therefore the limit he was bumping into, my box has 1GB), but for ball park figures they're worrying. The C++ echo server and simple connection opener that I used in the test can be downloaded from here; for best results run them on different machines.

Moving on the article discusses new features in .Net 2's socket classes; basically full support for AcceptEx. But, unfortunately, only a cursory mention of the potential denial of service attack that can come from accepting and receiving when a malicious client doesn't bother to send any data. I'm assuming you can access the accepted time on a socket via socket options so that you can protected against this. .Net 2's sockets also include support for DisconnectEx so that you can reuse your sockets. The author notes that queuing multiple accepts eats into the maximum number of connections that his server can achieve, but doesn't say if it's a one to one trade off. Interestingly both features have been supported in the underlying WinSock 2.0 layer since before .Net 1.0 so it's hardly that revolutionary to include support for them in .Net 2.0; they're just making the wrapper a bit more complete.

Finally the author covers the new tracing features in .Net 2's sockets; and you know what I think of tracing ;) Still, this kind of thing, in a framework library, could be useful.

The article ends by saying that "there are multiple approaches to improving the performance of socket applications. This article only scratched the surface of the full socket API." Well, yes... There are multiple approaches and, it would seem, that staying with C++ is the one to use if you want to handle a reasonable number of clients. One of the things that constantly bugs me about the .Net hype machine is that I don't think I've ever seen a .Net-head say something like "in this particular situation, if the performace of .Net isn't good enough for you, you might consider the added complexity of using C++"... I'm sure there are plenty of places where there is no reason to use C++ to obtain better performance but, in this case at least, it seems there might be...

I really wish this article had been written by someone who really knows their stuff, like Ian Griffiths. In my opinion this blog posting contains much better coverage on Async sockets in .Net, though it's not so hypey and it doesn't mention .Net 2.0 because it's pretty old. I'm always sceptical of articles that talk about performance without giving some figures to back up the claims and without providing enough details so that you can repeat the tests. And finally, I wish that the download could be built by the currently released version of Visual Studio rather than the latest beta. The code doesn't actually seem to use the .Net 2.0 features so why is it built in VS2005betaX?

All in all a disappointing article from many perspectives.

13 Comments

A article about "High-Performance Sockets" that
does not mention IOCP! Calling it "dissapointing" is
being very generous.

A google search on "C# iocp" show that other people have written about C#-"based" IOCP servers.

Regarding MSDN Magazine. I am reminded of this quote from Joel Spolsky:

"That's one camp. The other camp is what I'm going to call
the MSDN Magazine camp, which I will name after the
developer's magazine full of exciting articles about all the
different ways you can shoot yourself in the foot by using
esoteric combinations of Microsoft products in your own
software. The MSDN Magazine Camp is always trying to
convince you to use new and complicated external technology
like COM+, MSMQ, ..."

http://www.joelonsoftware.com/articles/APIWar.html

I actually assumed that the underlying implementation of the .Net async system does use IOCP and that in the world of .Net it's not necessary to mention the implemenation details...

Well, I want to know about the implementation details. If the async system is based on IOCP I will know that it has the potential to be useful (but not necessarily as good as in C++).

I think that a lot of the .NET code are wrappers versions of old windows code (code reuse). For example, I think the .NET Select call still has the 64 limit on the socket list.

I agree, to some extent. Though to be honest I'd rather just know that the async system is as powerful and flexible as the C++ version; I don't really care if they're the same and I'm quite happy to not need to know too much about them if they just happen to work.

Right now it doesn't look to be as flexible and that's the main problem that I have with .Net. It's fine if your problem fits with how .Net thinks you should solve it and less fine when you know that you can do this in C++ but .Net just doesn't expose the right bits of the underlying architecture... The connection limit, for example, is possibly just down to the default buffer size that's being used for reads being too big, and fixed. I don't know, but it would be a great shame if you can't work around the non-paged pool exhaustion in .Net by using the zero-byte read trick... Still, I don't know enough about the actual cause of the issue to do more than speculate at this time.

I agree that most of the .Net stuff is probably just wrappers, there's no real reason to do anything else, though I guess the wrappers could eventually be at the "subsystem" level so that .Net would be level with, rather than built on, Win32, with both calling down into the native call layer. Again, I don't much care as long as it works as well as they hype it ;)

I think the main problem is that the hype gets out of hand. .Net may well be good for everything some day but right now it doesn't seem to be the delivery platform of choice for shrink wrapper Microsoft apps so I'm guessing that at least in some places within MS .Net is viewed as something to get business apps built with... For that it's great; though the rumours I head at the moment are that UK investment banks are having as hard a time finding decent C# programmers as they are finding decent C++ guys and gals.

For the record, they do use IOCP under the covers. However, IIRC there is one deficiency - something like IOCP not being used for the accept operation. I forget the details, because I've never been bitten by it in practice.

I wasn't aiming to answer questions about the limits of performance in my blog entry, so I only got as specific as saying 1000 connections used only 1% CPU in my particular test scenario. I guess I could have tried to find a limit, but it wasn't the point I was trying to make with the article.

I had much more basic aims - my main goal was to get across the point that you don't necessarily need a thread to have work in progress... (The reason I wrote the article is because I keep meeting people who appear to believe that this is impossible!)

But since you're interested in finding the limits, did you check out the example Mike Woodring wrote? I linked to it in my blog. From the description he says he set out specifically to find the limits.

So if you try his example, that might let you make a direct comparison with the C++ server you wrote.

(And I'm flattered you'd rather I had written the article... Feel free to lobby the MSDN editors to get me to write more articles. :) )

Ian,

I had assumed that they used IOCP inside. In fact, given the talk in the article about adding AcceptEx support it pretty much had to. It's not clear if it supports ConnectEx; which would be nice but since that's relatively new it would have to fall back to some form of sync connect on older platforms.

I'll take a look at Mike's example (http://www.bearcanyon.com/dotnet/#ConnectionLimit.

Your article was just a considerably better .Net sockets article.

Since I'm working on investigating the limits of my C++ framework at the moment I took a look at Mike Woodring's .Net 1.0 sockets sample. His server allows a similar number of connections as my C++ code on my Windows XP box.

Thinking about the ~4000 limit that the author of the MSDN mag article came across I suspect it was the default value of the MaxUserPort registry value that was causing him problems, which makes me even less happy with his qualifications... ;)

Hi,

Here is an alternative solution. A IOCP/Socket wrapper. The author hope this library is well done and is waiting for peoples to help him to improve it ;-)

Take a look at :

http://devauthority.com/blogs/krys/archive/2006/06/13/HighPerformanceSocket.aspx

Here is another article about .NET Framework socket class performance: http://msdn2.microsoft.com/en-us/magazine/cc163356.aspx

I think native .NET socket class and synchronization primitives in .net don't allow to write a high performance .net server

There is too many overhead, take a look at this article: http://www.codeproject.com/KB/IP/high-performance-server.aspx

it explains the problems with .NET socket

Sorry but .NET socket class sucks in compare to xf.server.

Just take a look at the article: http://www.codeproject.com/KB/IP/high-performance-server.aspx

And compare the performance yourself.

James,

These links look a bit like spam to me, and the code project articles seem to have been deleted...

"link", thanks for the link, interesting stuff.

Leave a comment