High performance udp server. blocking or non-blocking? from

I read a lot about blocking and non-blocking sockets for udp, but it's hard for me to understand the merits of one over the other. The vast majority of comments on the Internet seem to indicate that non-blocking is better, but does not very accurately determine which scenarios they will be better in, and I did not find links to when blocking is preferable. I hope this issue helps the community shed some light on this topic.

a little background to my own set of problems, so the answers can be applied both specifically and to the general nature of the question. I have an udp server that I am writing, which will have 40 connections on the local network, due to which there will be a constant stream of data. Data transfer rates will be about 250 MB / s on average with peaks up to 500 + MB / s with avg datagram size of about 1400 bytes. Datagram processing is small, but due to the large volume of messages, efficiency and performance are a high priority to prevent packet loss.

since I could not find contextual information for something resembling this particular set of problems, I had to make several assumptions based on what I was able to learn about locking, not locking. I will just end this with my current hypothesis, and then open it to your input. basically, since it will be an almost constant stream of packets on every connection, I think a blocking socket would be preferable because the time that any recv function actually spends blocked will be very minimal compared to using an event-based event a model that will have an overwhelming number of triggers in asynchronous mode. I feel that my true set of problems will most likely be prioritizing 40 threads, which I plan to use to read from sockets ... so that everyone gets their share of CPU time. I can be wrong in my approach and ideas, so I hope and will be very grateful if the community can help shed light on this issue.

~ ~ Edit

while I'm concerned about how thread design will influence / integrate with the block / non-block issue. I'm really worried about how to consider locking / non-blocking in terms of my set of issues. if multithreading really becomes a problem, I can go with a thread pool solution.

~ ~ Edit2

Firstly, I wanted to tell the tank to you for the answers so far. some of you mentioned that a single thread / socket model with so many sockets might be a bad idea, and I admit that I tried with the solution myself. however, in one of the links in the nikolai answer, the author discusses a single-stream / socket model and refers to a very interesting article, which, as I thought, I would like to refer to, since it dissipates the many myths that I had about streams and events. based models: why events are a bad idea

+8
c design udp sockets
source share
4 answers

Not an answer, only some links, if you have not received them in your posts:

C10K issue by Dan Kegel,
High Performance Server Architecture by Jeff Darcy
Advanced polling APIs: epoll(4) , kqueue(2) .

Edit:

As stupid as possible, but I completely missed that you are working with UDP, so ...

Since UDP does not have connections at the protocol level, and if you do not need to work with different ports, you do not need 40 sockets on the server . Only one UDP server "socket will work for all clients. You can block this one socket that you like, just make sure that the socket receive buffer is large enough to take into account traffic traffic and not spend too much time processing each read.

+5
source share

I do not know that locking or non-locking has a significant performance advantage; this is more a question of what things your network I / O event loops will do:

  • If the only thing your network I / O stream does is listen for incoming UDP packets on the same socket, then blocking the I / O will probably work fine and make it easier to program.

  • If a network I / O stream needs to process multiple sockets, blocking I / O becomes problematic because if it blocks socket A, it won’t wake up to process data coming into socket B or vice versa. In this case, non-blocking I / O becomes preferable, since you can make your lock in select () or poll (), which will be returned whenever data is available in any of the watched sockets.

Please note that even in the non-blocking case, you will not want to cycle between packets, since burning processor cycles in thread A means that they will not be available for thread B, which will degrade performance. Therefore, if you do not block recv (), be sure to block in select () or poll () instead.

+2
source share
  • when using I / O lock, at some point in your program you should have a poll or choose, waiting for data on any of your files (in your sockets). Because if you read on any of your fh, without guaranteeing that the data is ready for it, it will be blocked, and the program will cease to manage other sockets. To avoid this and keep simple programs programs using IO locks, they are often written with one stream for each / fh socket, which eliminates the need for polling or selection.

  • If you use a non-blocking IO, your program will simply start and check for the presence of data, as they see every read. No need for a survey or choice. The program can still be quite simple, and there is no need to use a thread for this specific purpose.

I believe that the most efficient approach is to use polling or choose to manage multiple IOs at the same time (this may be a subset of all file descriptors shared between threads, if you prefer). It is more efficient than not blocking IO without polling or choosing, because this method basically tries to read on each socket most of the time is useless and has a cost. The worst method between the three is to use an IO lock with one fh for each thread due to the high cost of thread control compared to a read WOULDBLOCK return or poll.

This suggests that a non-blocking IO has another advantage: your program can have computations other than IO, and when you are blocked while waiting for I / O, you cannot do this. This can lead to the use of polling / selection with non-blocking IO or use it with a small timeout or even use a small specialized thread dedicated to IO and other threads for more intensive computing resources or programs.

In some cases, you also may not have a choice. I had to wait for data from a file installed via NFS. In this case, trying to establish a non-blocking IO is useless, since the NFS layer uses IO lock internally ...

You may also consider using asynchronous I / O. It is very effective, your program becomes "event driven". This is pretty common on Windows systems; I did not look at the current status of Linux asynchronous I / O development. Last time, I checked out some people who are working on adding asynchronous I / O to the kernel API, but I don’t know if it is stable or achieved by the core kernels.

+2
source share

I'm not sure that using 40 threads for 40 sockets is a great idea ... Of course, using a thread for each socket makes sense when you have a small number of sockets, however, while many threads just ask for a thread that is hungry, deadlocked, and missed packages.

As for locking and non-locking, remember that locking can be relatively expensive ... although, in my opinion, it is easier to work with. Asynchronous triggers, etc., Probably faster than when you need to block / wake up a thread.

0
source share

All Articles