views:

64

answers:

3

I'm looking at options for optimizing the number of concurrent connections my socket servers can handle and had an idea that hinges on being able to serialize C# sockets so that they can be removed from memory and then restored as needed. This scenario is only acceptable for me because sessions last for hours and the sockets are used very infrequently to send to clients and never for receiving during this time period. My current implementation is memory bound because I am holding each socket in memory for the lifetime of the corresponding client's session. Again, my thought is that if I were able to serialize the socket and write it to disc or stick it in a distributed cache/database/file store I could free up memory on the servers at the expense of some extra time required to process each send (i.e. deserialize the socket and then send on it). I've tried a couple of options, but ran into road blocks with each:

  1. Serialize/Deserialize the socket by reading and writing through a pointer to the object in memory. I can't seem to restore the socket after serialization.

  2. Use the Socket.DuplicateAndClose() method to get the SocketInformation, then serialize that and when needed restore the socket to the same process using the SocketInformation. I can't seem to use the socket once it is restored and I'm not sure this is going to amount to a significant memory savings as it seems to leave unmanaged resources in memory.

It seems to me that there should be a way to accomplish this. Ultimately, I'm looking for someone to either point me in the right direction or confirm that it is or isn't possible.

Any help is greatly appreciated!

+1  A: 

If I understand the question correctly, you are trying to serialize a Socket object, saving off its information (object contents), and then later trying to reconstitute that object with the saved info.

This won't work, because you can't simply save the contents of the Socket object and restore it later. Deep down, the socket uses an actual socket handler (open file descriptor) from the operating system. Saving and restoring this data won't reconnect the actual device handle within the operating system.

A socket requires physically connecting it (opening it) at the operating system level. This is similar to a Stream object. You can't simply save off the contents of the object and restore it later; it requires an attachment to a file descriptor within the operating system.

Loadmaster
But you could save off a file path along with the options that you originally used to access that file. Later you could load that data and open a new stream to that file.
Dr. Wily's Apprentice
Your understanding is correct and fair enough, I expected that it might not be possible. I guess I am just a bit surprised that I should need to involve the client in order to re-establish the server side resources for the socket.
djj
@Wily: Yes, but that's my point. You can't just re-create the object and have everything open and ready to use; you also have to re-open the underlying OS resource (socket, file, etc.). Saving the object's data does not keep the resource open.
Loadmaster
+4  A: 

This sounds like a good continuation to Alice's Adventures in Wonderland - a wonderful non-sense. You can't serialize a socket because this just doesn't make sense. Class "socket" (I mean not .NET Socket class but a type of objects which are called socket) don't support operation of "serialization" because sockets are (if we think in real-world objects) not data containers but gates to the communication channel. You can make a copy of the book, but it will be very hard to make a paper copy of a door.

Now about memory. You can have about 64K of sockets on your Windows system (I can be wrong with exact number, but the aproximate is this). Even with 100 bytes per socket you will occupy just 6 Mb of memory. In modern server OS (Windows, Linux, you name it) 6 Mb of user-mode memory is less than nothing. You will gain much more if you review overall application architecture.

Eugene Mayevski 'EldoS Corp
+1 for "paper copy of a door" analogy and for the notes on memory usage
Conrad Frix
I don't mean to harp on this too much, but a person could write down on a piece of paper which doors in a building are open and the angle at which each door is ajar. At a later time, you could refer to that paper and reset all of the doors in the building to their previous state. There is still the question of whether or not this is something that you would ever need to do. Perhaps not with sockets, but maybe with other non-data objects that do not appear to be serializable at first glance.
Dr. Wily's Apprentice
Thanks for the feedback, I'll definitely review and get to the bottom of why I am allocating so much memory for each connection. Does it really make sense though that I would need to involve the client when trying to re-establish the server side resources for a socket? I'm going for something like this http://blog.urbanairship.com/blog/2010/09/29/linux-kernel-tuning-for-c500k/ and even if I reduce memory usage per socket to next to nothing I'm likely to run into some other resource limitation as I continue to optimize and an approach like the one I mentioned could offer an improvement.
djj
@Dr Wily's Apprentice Exactly. If you are a carpenter, you can write down door parameters and create another door. But as an average Joe you can't. In case of socket, if you are a kernel-mode developer, you can trick the system by calling Duplicate Socket, closing original socket etc, or patch memory or do other tricks (we won't go into details here). But as a .NET programmer you can't doo much.
Eugene Mayevski 'EldoS Corp
@djj You can't connect the client cause as the name suggests,it's a client and it can be unavailable for connecting. more below.
Eugene Mayevski 'EldoS Corp
@djj One of possible approaches is to re-design the system a bit and send a reply to the client saying "here you have a token X that identifies your request. Reconnect in T seconds, send me a token X and I will probably have an answer for you". Then you have your client poll the server from time to time. However in many cases this will produce unnecessary overhead (for both network and CPU). So you should be looking for source of the problem somewhere else, not in network connection represented by socket.
Eugene Mayevski 'EldoS Corp
A: 

Your sockets is not the problem. They use very little memory. It's more likely how you treat inbound and outbound data that is the problem.

Are you allocating new (byte) buffers for each operation?

Create a buffer pool instead. Let the pool create a new buffer if it's empty. Don't forget to return a buffer when you are done with it.

What are you doing once you got the data in a buffer?

Are you building a string? If you have lots of incoming data or large strings you might want to switch to a StringBuilder. string.Format("{0}kdkd{1}jdjd{2}", var1, var2, var3) allocates less memory than var1 + "kdkd" + var2 + "jdjd" + var3.

How are you wrapping the socket?

You got a fat class with lots of stuff in it? Then it's your fat class that is the problem.

jgauffin