Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Performance / February 2004

Tip: Looking for answers? Try searching our database.

Proxying bytes from one socket to another...

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Kevin Z Grey - 23 Feb 2004 19:21 GMT
Heya

     I have a proxy server that essentially encapsulates received data by pre-prending a few integer values for each chunk of data read off the socket.  Now when the data is read, it is constructed into a "Message" object which is basically a struct of int, int, byte[], and is then dumped into a queue to schedule it to be sent by another Thread.  Since I have multiple Threads, I am forced to make a copy of the incoming byte array and queue the copy so that my data does not get fragmented.  The resulting code looks like this

        byte[] buff = new byte[1024]
                               ..
        if (conn.Available > 0
       
            // Read Byte
            int recv = conn.Receive(buff)
            byte[] t_buff = new byte[recv]
            Array.Copy(buff, 0, t_buff, 0, recv)
            // Construct Packe
            MessagePacket packet = MessagePacket.BuildPacket(t_buff)
            // Send it via the Outbound Socke
            EnqueueOutboundMessage(packet)
       

Is there a way to avoid an ArrayCopy in this scenario?  I have found that when receiving numerous small packets the lag time of the packets being proxied through the system is about 200ms, which is totally unacceptible for this server.  Can anyone offer some insight on how I can improve its perfomance

~~K
Justin Rogers - 26 Feb 2004 00:17 GMT
Suggestion, why are you using t_buff instead of just using buff?  In other
words, why the copy?  Does the length of the array have importance to your
message builder?
If so then pass in the recv variable using a special overload that only process
a portion of an
array.

If you still have lag times, you need to time each step and let us know what
lines are causing
the real lag.  I honestly can't see anything else wrong with the code below
unless
BuildPacket is awful in terms of performance or the Enqueue method is bad.

Signature

Justin Rogers
DigiTec Web Consultants, LLC.
Blog: http://weblogs.asp.net/justin_rogers

> Heya,
>
>       I have a proxy server that essentially encapsulates received data by pre-prending a few integer values for each chunk of data read off the socket.
Now when the data is read, it is constructed into a "Message" object which is
basically a struct of int, int, byte[], and is then dumped into a queue to
schedule it to be sent by another Thread.  Since I have multiple Threads, I am
forced to make a copy of the incoming byte array and queue the copy so that my
data does not get fragmented.  The resulting code looks like this:

> byte[] buff = new byte[1024];
>                                 ...
[quoted text clipped - 11 lines]
>
> Is there a way to avoid an ArrayCopy in this scenario?  I have found that when receiving numerous small packets the lag time of the packets being proxied
through the system is about 200ms, which is totally unacceptible for this
server.  Can anyone offer some insight on how I can improve its perfomance?

> ~~K
Tom Hall - 26 Feb 2004 02:50 GMT
200ms sounds suspiciously familiar - check into the Nagle algorithm which
waits up to 200ms attempting to prevent excess network traffic by waiting
for additional data to be gathered into one packet (send coalescing) - note
this only affects small packets like you said.  You can turn it off - its a
socket option (SocketOption.NoDelay).  You may need to turn it off on server
and client.

Also, if you do a network trace you may see delayed acknowledgement (also
200ms) from the client end where the socket is waiting after receiving
several packets hoping for you to send some data back that it can piggyback
the ACK packets on top of.  After about 200ms it gives up and sends the
ACK(s) by themselves - then the server is free to send more data. And it
repeats.  This is normal socket (TCP) protocol.

Typically you will see this if the server is sending only and the client end
is receiving only.  That is the client doesn't have any sort of reply to
send back after each message.  The sending of a reply in this case avoids
this situation and will cause a tremendous increase in speed but also causes
unnecessary traffic.  I did this in a protocol I developed for my
application and response went from 200ms to <1ms between packets.  You
should only do this if you have lots of small (<MTU) packets to send and you
can't coalesce them together or you NEED (my case) to get the data there
now, not 200ms from now.

If you haven't done a network sniff using Ethereal www.ethereal.com you
should (its free) - its invaluable to really see what's going on.

You can avoid the array copy if you *know* how big the header is before hand
(sounds like you do - you said 2 ints).  Leave room at the beginning of the
byte[] for the header, then use the Socket.Receive call that looks like
this:

int Receive(byte[] buffer, int offset, int size,SocketFlags socketFlags);

In your case, do

int recv=conn.Receive(buff,8,1024,SocketFlags.None);

Now, your data is in the array starting at byte 8, leaving room for you to
stick the header in and hand the whole thing off to the MessagePacket.  Of
course MessagePacket will have to be passed and track the length including
header as you are handing in the whole 1024 byte buffer - some of which
won't have data in it.

Are you sure you don't need a bigger buffer, the MTU on Ethernet is 1500
bytes so if you ever get packets bigger than your 1024 it will end up split
up as one big and one small receive typically which you would then forward
as two sends.  That's what the Nagle algorithm tries to avoid in the first
place!

HTH
Tom

> Heya,
>
>       I have a proxy server that essentially encapsulates received data by pre-prending a few integer values for each chunk of data read off the
socket.  Now when the data is read, it is constructed into a "Message"
object which is basically a struct of int, int, byte[], and is then dumped
into a queue to schedule it to be sent by another Thread.  Since I have
multiple Threads, I am forced to make a copy of the incoming byte array and
queue the copy so that my data does not get fragmented.  The resulting code
looks like this:

> byte[] buff = new byte[1024];
>                                 ...
[quoted text clipped - 11 lines]
>
> Is there a way to avoid an ArrayCopy in this scenario?  I have found that when receiving numerous small packets the lag time of the packets being
proxied through the system is about 200ms, which is totally unacceptible for
this server.  Can anyone offer some insight on how I can improve its
perfomance?

> ~~K

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.