Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

Help me understand/fix buffering issue for tcp?

by suaveant (Parson)
on Nov 18, 2011 at 20:11 UTC ( #938909=perlquestion: print w/replies, xml ) Need Help??

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

I have run across a problem in my local network communications, which should be lightning fast. Here is an example:
#!/idcom/bin/perl use IO::Socket::INET; use Time::HiRes qw( gettimeofday tv_interval ); use strict; our $PORT = 9991; if(fork) { my $s = IO::Socket::INET->new( LocalPort => $PORT, Listen => 5, Re +use => 1 ); my $c = $s->accept(); while(<$c>) { print {$c} $_; } } else { sleep 1; my $s = IO::Socket::INET->new( PeerAddr => 'localhost:'.$PORT ); for(1..5) { my $t0 = [gettimeofday]; print {$s} "func=mbs_descriptive&type="; print {$s} "&secid=313627KM2\n"; print ''.<$s>; print tv_interval( $t0, [gettimeofday] ),"\n"; } } OUTPUT func=mbs_descriptive&type=&secid=313627KM2 0.000458 func=mbs_descriptive&type=&secid=313627KM2 0.040329 func=mbs_descriptive&type=&secid=313627KM2 0.040905 func=mbs_descriptive&type=&secid=313627KM2 0.03986 func=mbs_descriptive&type=&secid=313627KM2 0.040938
now if I change the code to use
print {$s} "func=mbs_descriptive&type=&secid=313627KM2\n"; instead of print {$s} "func=mbs_descriptive&type="; print {$s} "&secid=313627KM2\n"; <C> I then get <C> func=mbs_descriptive&type=&secid=313627KM2 0.000448 func=mbs_descriptive&type=&secid=313627KM2 9.3e-05 func=mbs_descriptive&type=&secid=313627KM2 0.000161 func=mbs_descriptive&type=&secid=313627KM2 7.8e-05 func=mbs_descriptive&type=&secid=313627KM2 7.7e-05
A lot of our code kind of piecemeal prints to a socket like this, what is going on, and can I fix it without completely redesigning and existing codebase?

                - Ant
                - Some of my best work - (1 2 3)

Replies are listed 'Best First'.
Re: Help me understand/fix buffering issue for tcp?
by ikegami (Patriarch) on Nov 18, 2011 at 20:31 UTC

    Actually, I suspect the issue comes from lack of buffering.

    Because the output isn't buffered, two packets are sent out. The readline receives one, it doesn't have a newline, so it must wait for another. Lots of system calls. Lots more work.

    Or maybe the OS starts performing its own buffering when you send lots of short strings, and the delay is the OS making sure you're not about to send another.

    You can keep your code structure by turning off the buffering on the socket and explicitly flushing the socket when you output a newline.

    PS — You might benefit from examining the traffic with tcpdump.

      I always thought Perl's buffering waited for a newline, not that I can even remember where I came up with that from.

      It just seems to me a huge overhead compared to the time it actually takes to send the data, though I suppose it might not seem that long compared to general Internet speeds.

                      - Ant
                      - Some of my best work - (1 2 3)

      It seems you are right, if I turn off autoflush everything clears up... I think I can turn it off in most cases... it might be an interesting experiment.

                      - Ant
                      - Some of my best work - (1 2 3)

Re: Help me understand/fix buffering issue for tcp?
by andreas1234567 (Vicar) on Nov 21, 2011 at 14:31 UTC
    Isn't lightning fast socket-like communication what ZeroMQ supposedly is designed for? Some even writes:

    Performance matches and often exceeds that of raw sockets.

    No matter how great and destructive your problems may seem now, remember, you've probably only seen the tip of them. [1]
      Hrm, I've never seen that and am definitely going to have to look at it closer, but I don't know that it can fully solve my problem (if it solves it at all). Mainly because in the case that started me on this other people connect to the system and I assumed they'd all have to switch, too.

      I have a feeling the sockets are plenty fast enough, I think its buffering at some level that is causing the issue. Or something. What's really strange is the fact that when I print the line in two pieces it takes longer than if I send it all out as one, which is exactly what buffering is supposed to help with. I guess the buffering overhead could be just that high in which case maybe sensing a local connection and turning off buffering would do the trick (if you can even fully turn it off).

                      - Ant
                      - Some of my best work - (1 2 3)

Log In?

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

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2023-12-03 01:46 GMT
Find Nodes?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?

    Results (20 votes). Check out past polls.