Network I/O models
-
I've been trying to read about the best network I/O model and talked to people about which network I/O model is the best. Different answers from different peopels about the same model. Asynchronous I/O: One says it's the best model for concurrent operations, an other says it's bad because of a lot of synchronizing/locking when access shared data (such as client list on a server), then a third says, locking is not bad...man, this is kinda confusing. Synchronous I/O - using select(): I would say this one is bad, because then you have to wait for each operation to copmplete before you can move on. Other people says this is a great network I/O model. What is your opinion about the best network I/O model? Rickard Andersson Here is my card, contact me later! UIN: 50302279 Sonork: 37318
-
I've been trying to read about the best network I/O model and talked to people about which network I/O model is the best. Different answers from different peopels about the same model. Asynchronous I/O: One says it's the best model for concurrent operations, an other says it's bad because of a lot of synchronizing/locking when access shared data (such as client list on a server), then a third says, locking is not bad...man, this is kinda confusing. Synchronous I/O - using select(): I would say this one is bad, because then you have to wait for each operation to copmplete before you can move on. Other people says this is a great network I/O model. What is your opinion about the best network I/O model? Rickard Andersson Here is my card, contact me later! UIN: 50302279 Sonork: 37318
Asynchronous is very difficult to program. You really have to split up your operations into various states to process as different bits of I/O complete. Typically you'd use asynchronous I/Os to get the best out of a thread-pooled server - you can have more I/O pending than you have threads, and you can perform part of a second client's request while waiting for I/O for the first to complete. For best performance, you want to have a limited-size pool of threads, rather than one thread per client, for several reasons. Firstly there's overhead in creating and cleaning up threads. Secondly, each thread requires its own stack and possibly its own thread-local resources, which use up memory that you could be using for other things. Thirdly, the more threads there are which can run at any given time, the more time the OS spends switching between threads and the less actually doing work. The ideal is to have only one runnable thread per CPU. SQL Server uses this model (see Inside the User Mode Scheduler[^]). Writing your code this way can give you the maximum potential performance, but it's hard. Synchronous I/O is much easier: you simply write the code to perform the required steps in the required order. But you typically need more threads to achieve the same goal; if a thread is blocked waiting for I/O to serve one client, it can't serve another. Synchronisation is an issue whether you're using asynchronous or synchronous I/O, so long as you're using multiple threads that may access the same shared data. It's a fact of life in a multithreaded program. It doesn't affect your choice of sync or async I/O. Locking reduces your concurrency, sure, if two threads contend on the same shared data. You can potentially improve this by increasing the granularity of your locks - locking less data, and holding locks for less time. Windows provides the I/O completion port facility for simplifying and improving thread pooling. Threads and I/O handles can be associated with a particular completion port. Handles are associated by calling
CreateIoCompletionPort
; threads callGetQueuedCompletionStatus
to block waiting for an I/O (on any of the handles associated with the port) to complete. So far, so simple. The twist is that the completion port en