Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Old I/O thread per client model or NIO reactor pattern?

I am writing the server-side networking of a multiplayer game. The game is an RPG and it has the absolute maximum capacity of 2000 players, but it practically will max out at about 300 players, although it may be higher or lower. For the longest time, every time I had to do networking where it involved lots of clients, I have stuck to NIO because it did not require the use of hundreds of threads. Recently, I ran into a PowerPoint presentation where it described the two models in detail, and it almost made the thread-per-client model seem superior to NIO. I have also found places where it states that old IO can actually outperform NIO as well.

The PowerPoint can be found here (it is a bit old): http://www.mailinator.com/tymaPaulMultithreaded.pdf.

I have not written any content yet, so it would not be a problem for me to start at the beginning if I had to change my entire networking design. I am not pressured for time. Initially, I was designing a reactor pattern implementation with NIO (select an event, dispatch a handler to handle the event).

More information can be found here: http://en.wikipedia.org/wiki/Reactor_pattern

My entire reactor implementation is designed to use a single thread. Since I read that old IO can outperform, it actually put me in a dilemma. I do not want to design a complicated NIO system that uses multiple threads just to take full advantage of all the CPU power, but I also cringe at the idea of having a single application use 300+ threads. Which design is right for my purpose? The advantage of thread per client is that it truly uses harnesses all of the CPU power by nature, but at the same time, it bogs down the system. Not to mention, the stack size of a single thread takes up a lot of memory (when multiplied by a couple hundred times). Should I stick to the reactor pattern?

I know this question is a bit ambiguous, but I feel that I need to ask a question specifically for my situation because I could not find a question on this site nor a website where it addresses an issue of my sort. There was one about a game, but the game was meant to handle tens of thousands of players.

Thanks a lot! If you need any clarification, please ask!

like image 639
Martin Tuskevicius Avatar asked Apr 11 '12 20:04

Martin Tuskevicius


1 Answers

I do not want to design a complicated NIO system that uses multiple threads just to take full advantage of all the CPU power, but I also cringe at the idea of having a single application use 300+ threads. Which design is right for my purpose?

Our JVMs run with a lot more that 500 threads continually (right now they are sitting at ~700) with peaks in the 1000s. I see no reason to think that 800 threads is in some way "cringe" worthy. I'd start to worry when you reach 10,000 threads (as a ball park number) -- maybe less if you are running under 32bit. You certainly are going to have to allocate more memory as you get into the 1000s but anything under 1k threads should not be a problem. Here's a good page on thread creation numbers.

NIO is most efficient when you have a large number of connections with infrequent IO. It solves a lot of problems when it comes to asynchronous communication and there are things you can do with NIO that the "old IO" cannot do from a functional standpoint (interruptible channels and non-blocking IO for example) but the single thread handler is a much simpler model and I'm not surprised that it can outperform NIO implementations in many configurations. With NIO you are doing a lot of operations in Java code that are done for you in the JVM or even the kernel in native code. Multiplexing of streams and handling of ready IO are all things that you get "for free" (in terms of complexity) with the "old IO" model.

I would keep it simple and stick with the thread-per-client pattern until you have good reason to take the complexity hit.

like image 123
Gray Avatar answered Oct 14 '22 14:10

Gray