A couple of days ago I had to investigate a problem where my application was showing abnormally high CPU usage when it was (apparently) in idle state. I tracked the problem down to a loop which was meant to block on a recvfrom call while the socket had been set to O_NONBLOCK-ing resulting in a spin lock. There were two ways of solving the problem: set the socket to blocking or poll for available data on the socket using poll or select. I chose the former as it was simpler. But I am wondering why any one would create a non-blocking socket and then poll on it separately. Doesn't a blocking socket do the same? What are the uses cases where one would use a non-blocking socket and poll combination? Are there any advantages to it in general cases?
Using poll() or select() with a non-blocking file descriptor gives you two advantages:
You can set a timeout to block for;
You can wait for any of a set of file descriptors to become useable.
If you only have a single file descriptor (socket) to wait for, and you don't mind waiting indefinitely on it, then yes; you can just use a blocking call.
The second advantage is really the killer use case for select() and friends. It means that you can handle multiple socket connections, as well as standard input and standard output and possibly file I/O, all with a single thread of control.
I´m posting here, because although the question is old. It came up in my google search somehow and has definitely not been answered properly.
The accepted answer merely highlights two advantages of using non-blocking sockets but does not really go into detail or answer the actual question.
NOTE : Unfortunately most online "tutorials" or code snippets only feature blocking socket code, so knowledge on non-blocking sockets is less spread.
As to when you would you use one compared to the other ... in general blocking sockets are only used in online code snippets. In all (good) production applications non-blocking sockets are used. I´m not ignorant, if you know of an implementation that uses blocking sockets (and sure that´s very well possible in combination with threads) - or let´s be more specific that uses blocking sockets in a single thread - please do let me know.
Now I can give you a very easy to understand example, and there are many others out there. Let´s take the example of a gaming server. Games advances at ticks, regular intervals where the game state progresses whether or not the player provides input (mouse / keyboard) to change the state of the game. Now when sockets come into play in Multiplayer games - if you were to use blocking sockets the game state would not advance unless the players were sending updates - so if they have internet problems, the game state would never consistently update and propagate changes to all players. You would have a rather choppy experience.
Now using non-blocking sockets, you can run the gameserver on a single-thread, updating the gamestate as well as the sockets, with a ... let´s say 50ms timeout interval - and socket data is only read from connected users when they actually send something, and then fed into the server simulation, processed and fed into the game state calculation for the next tick.
resulting in a spin lock.
That condition normally is called a tight loop.
There were two ways of solving the problem: set the socket to blocking or poll for available data on the socket using poll or select. I chose the former as it was simpler.
Are you sure that other code parts do not already use poll() (or select()) and expect the socket to be in non-blocking mode?
Otherwise, then yes, the switch to the blocking mode is the simplest solution.
Best backward-compatible solution would have been before calling recvfrom() to use poll() to wait for the socket to become readable. That way ensures that other parts of the code would work precisely as before.
But I am wondering why any one would create a non-blocking socket and then poll on it separately. Doesn't a blocking socket do the same?
For the case of recvfrom() no major difference is known to me.
What are the uses cases where one would use a non-blocking socket and poll combination? Are there any advantages to it in general cases?
Could be a simple coding mistake. Or somebody might have thought that recv'ing in tight loop would somehow increase the performance.
It is always better to make sockets as nonblocking because even a blocking socket becomes ready state sometimes (when data arrived but has checksum error and that is discarded) - even when there is no data to read. So make it nonblocking, wait for the data availability through poll then read. I think this is the main advantage.
Related
I'm coding for a linux platform using C. Let's say I have 2 threads. A and B.
A is an infinite loop and constantly trying to find out if there is data on the socket localhost:8080, where as B is a thread that spends most of its time in a blocked state until A calls mutex unlock function on a mutex that B uses to block itself. A will unlock B when it received appropriate data on the socket.
So you see here is a problem. B is "event driven" largely whereas A is in a constant running state. My target platform isn't resource rich so I wish A could be "activated" and enter running state only when it received data on socket, instead of constantly looping.
So how can I do that? If it matters - I wish to do this for both UDP and TCP sockets.
There are Multiple was of doing what you want in a clean was. One approach, you are kind of using already, is a event system. A real event system would be overkill for the kind of problem you are dealing with, but can be found here. This is a (random) better implementation, capable of listening for multiple file descriptors and time based events, all in a single thread.
If you want to build one yourself, you should take a look at the select or poll function.
But I agree with #Jeremy Friesner, you should definitely use the functions made for socket programming, they are perfect for your kind of problem. Only use the event system approach if you really need it (with multiple sockets/timed events).
You simply call recv (or recvfrom, recvmsg, etc) and it doesn't return until some data has been received. There's no need to "constantly try to find out if there is data" - that's silly.
If you set the socket to non-blocking mode then recv will return even if there's no data. If that's what you're doing, then the solution is simple: don't set the socket to non-blocking mode.
I've seen a few write-ups comparing select() with poll() or epoll(), and I've seen many guides discussing the actual usage of select() with multiple sockets.
However, what I can't seem to find is a comparison to a non-blocking recv() call without select(). In the event of only having 1 socket to read from and 1 socket to write to, is there any justification for using the select() call? The recv() method can be setup to not block and return an error (WSAEWOULDBLOCK) when there is no data available, so why bother to call select() when you have no other sockets to examine? Is the non-blocking recv() call much slower?
You wouldn't want a non-blocking call to recv without some other means for waiting for data on the socket as you poll infinitely eating up cpu time.
If you have no other sockets to examine and nothing else to do in the same thread, a blocking call to read is likely to be the most efficient solution. Although in such a situation, considering the efficiency of this is like to be premature optimisation.
These kinds of considerations only tend to come into play as the socket count increases.
Nonblocking calls are only faster in the context of handling multiple sockets on a single thread.
If there is no data available, and you use non-blocking IO, recv() will return immediately.
Then what should the program do ? You would need to call recv() in a loop until data becomes available - this just uses CPU for pretty much no reason.
Spinning on recv() and burning CPU in that manner is very undesirable; you'd rather want the process to wait until data becomes available and get woken up; that's what select()/poll() and similar does.
And, sleep() in the loop in order to not burn CPU is not a good solution either. You'd introduce high latency in the processing as the program will not be able to process data as soon as the data is available.
select() and friends let you design the workflow in such a way that slowness of one socket does not impede the speed at which you can serve another. Imagine that data arrives fast from the receiving socket and you want to accept it as fast as possible and store in memory buffers. But the sending socket is slow. When you've filled up the sending buffers of the OS and send() gave you EWOULDBLOCK, you can issue select() to wait on both receiving and sending sockets. select() will fall through if either new data on the receiving socket arrived, or some buffers are freed and you can write more data to the sending socket, whichever happens first.
Of course a more realistic use case for select() is when you have multiple sockets to read from and/or to write to, or when you must pass the data between your two sockets in both directions.
In fact, select() tells you when the next read or write operation on a socket is known to succeed, so if you only try to read and write when select allows you, your program will almost work even if you didn't make the sockets non-blocking! It is still unwise to do, because there exist edge cases when the next operation still may block despite select() reported that the socket as "ready".
On the other hand, making the sockets non-blocking and not using select() is almost never advisable because of the reason explained by #Troy.
in Unix Network Programming by Stevens et al non-blocking sockets are illustrated with code making use of select call. The very same call that usually selects between blocking file descriptors.
My understanding was that non-blocking design was exactly an alternative to select: instead of being blocked in select call, my code could loop checking non-blocking descriptors and performing something else on top of that. Was my understanding wrong or is there anything enigmatic about select call that makes it inevitable in non-blocking design?
Down to practicalities, I need to work with a large number of tcp sockets putting "personal" timeout on each of them. I thought of using non-blocking design and looping through correspondent arrays. Would it be appropriate without select?
Thank you.
A customizable inactivity timer shouldn't really have anything to do with the select() call. maintain your array of timers separately, update them on every tick, or every <x> iterations through your event loop, reset any timer each time the associated socket has activity, close it when inactivity reaches threshold. That's got nothing whatsoever to do with how you actually handle input/output.
Whether or not you use select() is orthogonal to whether you use non-blocking sockets. select() isn't there to keep you from blocking on reads, after all. What select() is for is to keep you from blocking when you don't want to. (And not just on reads: you can always call select() with a zero timeout, and select() won't block either). Also, it provides a mechanism for knowing when there's input that's much more efficient than "iterate over my entire set of sockets, trying a nonblocking read() on each one in turn".
I am writing a client that receives UDP datagrams from a single sender. All IO will be done in a single thread. Generally, there will either be no data, or a 30 MBit/s stream. My primary concern is in keeping latency as low as possible.
The plan is to block, waiting for data, in a loop with a short-ish timeout, so that the IO thread can be responsive to shutdown requests, etc.
I am inclined to use a blocking socket, set a timeout on it, and do a recvfrom() call. However, this seems to be much less common than a select()/poll() and recvfrom() combination on a nonblocking socket.
Given that I am only working with a single socket, it seems that the nonblocking approach is needlessly complicated. Am I missing something else? Is there a reason to prefer nonblocking sockets in this particular case?
If you have a dedicated thread for handling the socket then asynchronous I/O, select etc are useless. What you want is simply recvfrom(2) and handle the data as quickly as possible.
Any fancy mechanisms (epoll, libaio, etc.) won't help you get more speed out of your application.
With only a few peers, (and 'one' is surely in this set:), a thread with a blocking socket should be fine. The code is easier to write since state can be maintained in the dedicated thread - no need for the state-machines that are usually required with a non-blocking system.
Short timeout - do you need this? Do you shutdown this subsystem before app close? If not, could you just let it be killed by OS?
If you have to shut down the thread system, you could set some 'terminate' flag and send yourself a UDP message to unblock the thread so it realises it has to die.
Rgds,
Martin
I do not understand what the difference is between calling recv() on a non-blocking socket vs a blocking socket after waiting to call recv() after select returns that it is ready for reading. It would seem to me like a blocking socket will never block in this situation anyway.
Also, I have heard that one model for using non blocking sockets is try to make calls (recv/send/etc) on them after some amount of time has passed instead of using something like select. This technique seems slow and wasteful to be compared to using something like select (but then I don't get the purpose of non-blocking at all as described above). Is this common in networking programming today?
There's a great overview of all of the different options for doing high-volume I/O called The C10K Problem. It has a fairly complete survey of a lot of the different options, at least as of 2006.
Quoting from it, on the topic of using select on non-blocking sockets:
Note: it's particularly important to remember that readiness notification from the kernel is only a hint; the file descriptor might not be ready anymore when you try to read from it. That's why it's important to use nonblocking mode when using readiness notification.
And yes, you could use non-blocking sockets and then have a loop that waits if nothing is ready, but that is fairly wasteful compared to using something like select or one of the more modern replacements (epoll, kqueue, etc). I can't think of a reason why anyone would actually want to do this; all of the select like options have the ability to set a timeout, so you can be woken up after a certain amount of time to perform some regular action. I suppose if you were doing something fairly CPU intensive, like running a video game, you may want to never sleep but instead keep computing, while periodically checking for I/O using non-blocking sockets.
The select, poll, epoll, kqueue, etc. facilities target multiple socket/file descriptor handling scenarios. Imagine a heavy loaded web-server with hundreds of simultaneously connected sockets. How would you know when to read and from what socket without blocking everything?
If you call read on a non-blocking socket, it will return immediately if no data has been received since the last call to read. If you only had read, and you wanted to wait until there was data available, you would have to busy wait. This wastes CPU.
poll and select (and friends) allow you to sleep until there's data to read (or write, or a signal has been received, etc.).
If the only thing you're doing is sending and receiving on that socket, you might as well just use a non-blocking socket. Being asynchronous is important when you have other things to do in the meantime, such as update a GUI or handle other sockets.
For your first question, there's no difference in that scenario. The only difference is what they do when there is nothing to be read. Since you're checking that before calling recv() you'll see no difference.
For the second question, the way I see it done in all the libraries is to use select, poll, epoll, kqueue for testing if data is available. The select method is the oldest, and least desirable from a performance standpoint (particularly for managing large numbers of connections).