Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Efficient non-blocking UDP server

by crenz (Priest)
on Mar 19, 2004 at 21:12 UTC ( [id://338175]=perlquestion: print w/replies, xml ) Need Help??

crenz has asked for the wisdom of the Perl Monks concerning the following question:

Fellow monks,

I'm working on implementing a UDP server that dispatches messages to different callback functions, depending on the content. The problem is that I'm not sure which is the best way to implement a non-blocking server efficiently. My list of priorities (in this order):

  • Portable - Should work on at least Mac OS X and Windows
  • Fast - Ideally, I want to be able to process hundreds of messages per second in the background while the user is fiddling around with the GUI in the foreground
  • Simple - Should be easy to understand and easily packaged in a module. Should be pure Perl.

Would it be more efficient to use IO::Socket in non-blocking mode and let the user call a $server->if_you_got_a_message_then_do_something() in a while loop (ie. polling) or should I use threading?

Replies are listed 'Best First'.
Re: Efficient non-blocking UDP server
by matija (Priest) on Mar 19, 2004 at 21:32 UTC
    You should only ever use polling if there is absolutely no other way to do it. Any (OK, almost any) other method is going to be more efficient.

    Waiting at the socket isn't actually your biggest problem. Your problem is in the callback functions you're dispatching. If you can't guarantee that no callback function will use more than 1/100 of a second, you can't guarantee 100 messages per second in a single threaded server.

    The easy way of doing such a server is to block waiting for a new packet, then spawn a thread (or a process) to handle it.

    The more sophisticated servers (Apache, for instance) have dispatching mechanisms that apportion requests to pre-spawned processes so that the spawning doesn't delay processing.

    Of course, the faster your server, the more complex is the dance required to keep all the components fed and synced.

    I'm afraid that for Portable/Fast/Simple you will be lucky to get two out of three.

Re: Efficient non-blocking UDP server
by NetWallah (Canon) on Mar 19, 2004 at 21:40 UTC
    Take a look at the new Net::NBsocket module , which creates non-blocking sockets.

    Here are some recent code snippents I wrote, that may be relevent as an alternative to NBsocket:

    Offense, like beauty, is in the eye of the beholder, and a fantasy.
    By guaranteeing freedom of expression, the First Amendment also guarntees offense.
Re: Efficient non-blocking UDP server
by RMGir (Prior) on Mar 19, 2004 at 21:36 UTC
    Server?

    From your description, you are planning on being the recipient of the UDP messages, right? That strikes me as making you the client.

    In any case, I'm not sure you're going to be able to do a GUI and process 100's of packets per second in perl, with an interpretation step to do the dispatch.

    The easiest way to try, though, might be to look at POE's UDP sample, and POE/Tk or POE/Gtk for the GUI aspects.


    Mike
Re: Efficient non-blocking UDP server
by calin (Deacon) on Mar 20, 2004 at 16:47 UTC

    Think your UDP-receiving code as an interrupt handler and try applying common sense from there. An interrupt handling routine should finish in short, quasi-constant time, and definitely its execution time should not depend on circumstances outside its control.

    I suggest pushing your received packets onto a safe queue right away (without deciding upon their content), and let other thread/process handle them. (Thread::Queue looks interesting).

      I would be surprised if Thread::Queue would have the performance needed for handling hundreds of UDP packets.

      If you realise that a shared array (to which Thread::Queue is a very simple frontend) stores its valus both in the current thread as well as in the hidden background thread. Not very performance friendly.

      If you want to try Thread::Queue for this application, make sure that you have Perl 5.8.1 or higher, as 5.8.0 has a severe memory leak with shared arrays.

      Liz

        liz, thanks for feedback. I didn't realize Tread::Queue could be so costly ; my suggestion was the result of a mere query on CPAN by the word queue ; the module looked interesting.

        There's another thing: I suppose the OP requires hundreds of packets per second as a burst condition, right? The perspective of coping with a sustained condition like that, I mean receiving and processing that amount in pure Perl, in real time, looks dim. Even if the receiving routine is fast enough, the queue would quickly fill up. (there's a discussion on what the "processing" amounts to). Anyway, that calls for optimized C code, IMHO.

        All in all, I think the main idea of my original reply (treat your network code as an interrupt handling routine) is still valid in the context of datagram protocols.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://338175]
Approved by valdez
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (5)
As of 2024-04-20 00:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found