Networking stack performance

I’m trying to migrate from NetDuino Plus 2. To test all the stuff i got a g120E development board. After “porting” the sw , the first observation is that the network is way too slow comparing to netduino. I’m getting not more than 8-10 Kbps, even a simple ping works weird, sometimes i’m getting more than a second response time or even timeouts.
Most likely i’m doing something wrong, but after browsing all related to the network/Ethernet posts i couldn’t find much about the performance. Only in one of the posts somebody has mentioned 500 Kbps (would be ok for me) .
I just wanted to know what i can potentially get out of the board , before digging in and trying to figure out what is wrong

2 Likes

welcome.

great first post. Networking perf is not usually the bottleneck, it’s your code. Show us your code that you say has poor ping response so we have a starting point to work from.

Hi,
did you try to set another MAC Address for you G120E with MFDeploy and are you sure that you don#t have two devices with the same MAC in your network?

It is ICMP ping for out of the box board, nothing was running on the board. The board is directly connected to my laptop. Comparing to the NetDuino plus 2 board where ping runs response time from 8ms to maximum 20ms , on the eval G120E board the ping response time was from 16ms to 1+ seconds with 5% timeouts.

The program is straight forward too. I just wanted to know what performance people get with G120E BuiltIn Ethernet. I would guess that the IP stack is the same on NetDuino and G120E, so it must be something in the drivers .

public Server()
{
_eth = new EthernetBuiltIn();
_eth.Open();

}

private void SocketSetup()
{
listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listeningSocket.Bind(new IPEndPoint(IPAddress.Any, Port));

//listeningSocket.ReceiveTimeout = -1;
//listeningSocket.SendTimeout = -1;
listeningSocket.Listen(5);
}

private void WaitingForRequest()
{
while (true)
{
try
{
using (Socket clientSocket = listeningSocket.Accept())
{
[b]// …
// SOME HTTP PARSING HEADERS RELATED CODE
// …

                    SendResponse(tempRequest);[/b]
                }
                try
                {
                    //Close client, otherwise the browser / client won't work properly
					// THE SOCKET CLOSE DOESN'T WORK IMMIDIATLY 
                    clientSocket.Close();
                    Debug.Print("Socket Closed");
                }
                catch (Exception ex)
                {
					clientSocket.Close();
					Debug.Print(ex.ToString());
                }
            }
            catch (Exception ex)
            {
                
                 [b]//=======>  I'M OK WITH 5 TIMES EXCEPTIONS ON ACCEPT [/b]
	     Debug.Print("Failed to Accept Connections: " + ex.Message);
              //  DEBUG PowerState.RebootDevice(false);
            }
        }
    }
	
   public override bool SendResponse(Request e)
    {
        string filePath = "";
        using (Util.ExtensionMethods em = new ExtensionMethods())
        {
            filePath = em.Replace("/SD/"+e.URL, '/', '\\');
        }
        bool isDirectory = false;

        //File found check
        if (!CheckFileDirectoryExist(ref filePath, out isDirectory))
            Send404_NotFound(e.Client);


            string mType = MimeType(filePath);

            //File sending
            using (FileStream inputStream = new FileStream(filePath, FileMode.Open))
            {
                Send200_OK(mType, (int)inputStream.Length, e.Client);
				
				// I'VE TRIED BOTH SENDING IN CHUNKS OR AS ONE BUFFER
				// SAME RESULT
                // byte[] readBuffer = new byte[Settings.FILE_BUFFERSIZE];  // SENDING IN CHUNKS 
                byte[] readBuffer = new byte[inputStream.Length]; // SENDING ONE BUFFER
                int sentBytes = 0;

                //Sending parts in size of "Settings.FILE_BUFFERSIZE"
                while (sentBytes < inputStream.Length)
                {
                    int bytesRead = inputStream.Read(readBuffer, 0, readBuffer.Length);
                    try
                    {
                        if (SocketConnected(e.Client))
                        {
		     [b] // =============================
		      // THIS IS WHERE THE DELAY HAPPENS , IT TAKES TOOOO MUCH TIME TO SEND THE DATA 
		       // =============================
                            sentBytes += e.Client.Send(readBuffer, bytesRead, SocketFlags.None); [/b]
                        }
                        else
                        {
                            e.Client.Close();
                            return false;
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.Print("Error sending data");
                        try
                        {
                            e.Client.Close();
                        }
                        catch (Exception ex2)
                        {
                            Debug.Print("Error closing socket");
                        }

                        return false;
                    }
                }
            }
        }

        return true;
    }

}

If you surround your code snippet with the “format as code” tag, it is much easier to read. (I also pasted it into Slickedit and “beautified” it)

public Server()
{
   _eth = new EthernetBuiltIn();
   _eth.Open();
}

private void SocketSetup()
{
   listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
   listeningSocket.Bind(new IPEndPoint(IPAddress.Any, Port));
   //listeningSocket.ReceiveTimeout = -1;
   //listeningSocket.SendTimeout = -1;
   listeningSocket.Listen(5);
}

private void WaitingForRequest()
{
   while (true)
   {
      try
      {
         using (Socket clientSocket = listeningSocket.Accept())
         {
            // ........
            // SOME HTTP PARSING HEADERS RELATED CODE
            // ........

            SendResponse(tempRequest);
         }
         try
         {
            //Close client, otherwise the browser / client won't work properly
            // THE SOCKET CLOSE DOESN'T WORK IMMIDIATLY
            clientSocket.Close();
            Debug.Print("Socket Closed");
         }
         catch (Exception ex)
         {
            clientSocket.Close();
            Debug.Print(ex.ToString());
         }
      }
      catch (Exception ex)
      {

         //=======> I'M OK WITH 5 TIMES EXCEPTIONS ON ACCEPT
         Debug.Print("Failed to Accept Connections: " + ex.Message);
         // DEBUG PowerState.RebootDevice(false);
      }
   }
}

public override bool SendResponse(Request e)
{
   string filePath = "";
   using (Util.ExtensionMethods em = new ExtensionMethods())
   {
      filePath = em.Replace("/SD/" + e.URL, '/', '\\');
   }
   bool isDirectory = false;

   //File found check
   if (!CheckFileDirectoryExist(ref filePath, out isDirectory))
      Send404_NotFound(e.Client);


   string mType = MimeType(filePath);

   //File sending
   using (FileStream inputStream = new FileStream(filePath, FileMode.Open))
   {
      Send200_OK(mType, (int)inputStream.Length, e.Client);

      // I'VE TRIED BOTH SENDING IN CHUNKS OR AS ONE BUFFER
      // SAME RESULT
      // byte[] readBuffer = new byte[Settings.FILE_BUFFERSIZE]; // SENDING IN CHUNKS
      byte[]readBuffer = new byte[inputStream.Length]; // SENDING ONE BUFFER
      int sentBytes = 0;

      //Sending parts in size of "Settings.FILE_BUFFERSIZE"
      while (sentBytes < inputStream.Length)
      {
         int bytesRead = inputStream.Read(readBuffer, 0, readBuffer.Length);
         try
         {
            if (SocketConnected(e.Client))
            {
               // =============================
               // THIS IS WHERE THE DELAY HAPPENS , IT TAKES TOOOO MUCH TIME TO SEND THE DATA
               // =============================
               sentBytes += e.Client.Send(readBuffer, bytesRead, SocketFlags.None);
            }
            else
            {
               e.Client.Close();
               return false;
            }
         }
         catch (Exception ex)
         {
            Debug.Print("Error sending data");
            try
            {
               e.Client.Close();
            }
            catch (Exception ex2)
            {
               Debug.Print("Error closing socket");
            }

            return false;
         }
      }
   }
}
1 Like

AFAIK, netduino did not implement an onboard IP stack and used Wiznet modules for that; so it’s completely feasible that there will be a performance difference as I’d expect Wiznet to leverage in-silicon response to ICMP whereas the netmf stack would need to respond in the G120’s case.

Network throughput is not a simple thing to measure nor a sensible discussion point, so you won’t find an answer to your question. It all comes down to code, and what you want to do in the code that’s also handling networking. If you wanted to do a full video stream over IP then there is no way G120 would be suitable, but if you wanted to do periodic hi-res still image transfer in a short time then yes it can (and maybe at a sustained rate that you think you want). Without telling us more about what you want to do and how you think you’re going to achieve that, we’re all in the dark and you won’t get closer to an answer. If you don’t want to tell us or can’t (intellectual property protection) then I’d consider contracting GHI directly as they will work under an NDA

@ Brett, @ mtylerjr

Thanks for the answers and information . My problem is not the application networking performance , i use short messages to send the info from a lidar sensor. It is a webserver that takes too much time to show up, for example sending a jquery lib (~90KB) takes up to 2 mins :frowning:

Has anybody tried to use Netduino.IP [url]Introducing Netduino.IP, the shiny new TCP/IP stack for NETMF - Netduino.IP Technical Preview - Netduino Forums. From a quick glance it should be pretty simple to port/use .