Why is NetworkStream.Read so slow?

TimVK picture TimVK · Mar 13, 2012 · Viewed 8k times · Source

I know, there are already a lot of similar questions here but I did not found a solution to make it faster or the reason why it is so slow?

We have an application in C#.NET that needs to communicate through TCP to a device that answers on the same TCP stream (all in bytes). The sending of messages goes pretty fast (about 20 ms) but when we Read the data from the TCP socket with the NetworkStream.Read() method (or similar Socket.Receive()) it takes about 600ms. I get this number by starting a stopwatch before the Read method and stop it right after the Read.

I also log the traffic with Wireshark and there I see that the communication goes pretty fast (with the TCPNoDelay and TCPAckFrequency registry hacks) but there I saw that the following message that is send to the device is after 600ms (after the reading of the previous answer).

The devices cannot handle multiple messages at once and they also answer with a custom made Acknowledge so that our program knows that the last sent message is received and constructed right.

Ok here is some testing code that I have for a Console application and even that has the problem of the 600ms delay at reading.

try
{
   if (!retry)
   {
      Console.WriteLine("Please enter the IP address you want to check:");
      ip = Console.ReadLine();
      Console.WriteLine("Please enter the port where you want to check on:");
      port = Convert.ToInt32(Console.ReadLine());
      Console.WriteLine("Connecting to {0}: {1}", ip, port);
      Console.WriteLine("Please enter the message you want to write to the specified port:");
      message = Console.ReadLine();
   }
   tcp = new TcpClient(ip, port);
   tcp.NoDelay = true;
   tcp.Client.NoDelay = true;
   Stopwatch sWrite = new Stopwatch();
   Stopwatch sRead = new Stopwatch();
   Stopwatch sDataAvailable = new Stopwatch();
   using (NetworkStream ns = tcp.GetStream())
   {
      Byte[] data = System.Text.Encoding.ASCII.GetBytes(message + "\r");
      sWrite.Start();
      ns.Write(data, 0, data.Length);
      sWrite.Stop();
      data = new byte[256];
      sRead.Start();
      Console.WriteLine("There is data on the socket: {0}", ns.DataAvailable);
      int readBytes = ns.Read(data, 0, data.Length);
      sRead.Stop();
      message = System.Text.Encoding.ASCII.GetString(data, 0, readBytes);
      Console.WriteLine(message);
   }
   Console.WriteLine("The reading speed is {0} and the writing speed is {1}", sRead.ElapsedMilliseconds, sWrite.ElapsedMilliseconds);
}
catch { }
finally
{
   tcp.Close();
}

And this gives the following result: The reading speed is 500 and the writing speed is 0

Answer

TimVK picture TimVK · Jun 7, 2012

I just found the solution to my slow network problem and I want to share it with all of you. You never know when or who might experience the same problem.
Earlier this day I came to this site TcpClient receive delay of over 500ms and there I followed the solution of the registry hack of the PSH bit (IgnorePushBitOnReceives) and that solved it. So we have now temporary fast communication back because I think the people of the hardware where we are working with, just need to set the Push flag of the TCP messages.