Ethernet Speed

I just changed one of my applications to use a telnet connection as the "console" in place of a serial port, due to some functional characteristics of some of the serial ports I've been unable to work around. I was surprised/disappointed to find the Ethernet connection is quite a bit slower than the serial port. My application outputs a great deal of debugging information, amounting to as much as ~11Kbytes/second. Ethernet tops out at just under half that (5.25Kbytes/second).

Anyone know what the limiting factor is there? Is it the SPI connection? Buffering? Other? This is on a Due with a W5100 Ethernet adaptor, if that matters.

Also, the EthernetClient.connected() call seems not to work - it ALWAYS retrurns false - i.e. NOT connected.

Regards,
Ray L.

Guessing, I'd bet that the ethernet libraries do a poor job of packetizing "stream" data like that generated by xxx.print(), so that you wind up hitting a "packets/second" limit rather than an actual bytes/second limit. Efficiently packetizing stream data is actually a relatively difficult problem.

RayLivingston:
Anyone know what the limiting factor is there? Is it the SPI connection? Buffering? Other?

It's the code, man!

SPI is the fastest data interface on Arduino boards.

But your code will have to use no-nonsense-programming logic to provide high data rates. It's easy to pull the data rate down to a few percent of the maximum possible data rate with simply using less than perfect programming logic.

jurs:
It's the code, man!

SPI is the fastest data interface on Arduino boards.

Actually, on my board it's not. I run I2C at 2MHz. What is the SPI clock rate?

jurs:
But your code will have to use no-nonsense-programming logic to provide high data rates. It's easy to pull the data rate down to a few percent of the maximum possible data rate with simply using less than perfect programming logic.

The code I used for testing is about as no-nonsense as it gets - a For loop sending a single 50-character string using EthernetClient.print, and counting how many times it can be sent in 30 seconds. The same code, using Serial, will send almost twice as much data. So, the Print overhead is not the issue, as Print is exactly the same for both devices, other than the low-level character I/O.

Regards,
Ray L.

Delta_G:
I thought you could run the SPI interface at 8MHz.

Maybe so, but the question is: What speed is it actually running? Without spending an hour with the SAM3X datasheet, I can't tell what speed is actually being used, but I'd be amazed if it was anywhere near that fast.

Regards,
Ray L.

If the comments in the SPI source code can be believed, the SPI I/F is programmed for 4MHz, which is FAR faster than the 115KBaud I use on Serial. Yet Serial is twice as fast....

Regards,
Ray L.

RayLivingston:
Actually, on my board it's not. I run I2C at 2MHz. What is the SPI clock rate?

Perhaps you can explain a bit more detailed what you are doing actually.
I'm just using an UNO board, stacked with an Ethernet shield, and use all the default settings.

I've done a short test which shows me (using an UNO and Ethernet Shield):

Bytes sent: 46000
Time used:  0.909 seconds

RayLivingston:
The code I used for testing is about as no-nonsense as it gets - a For loop sending a single 50-character string using EthernetClient.print, and counting how many times it can be sent in 30 seconds.

I got my test result with this code, using the Arduino as a HTTP webserver for testing:

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};

char testStr[]="The quick brown fox jumps over the lazy dog.\r\n";

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  // start the Ethernet connection and the server:
  Ethernet.begin(mac);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}


void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/plain");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println();
          unsigned long time=millis();
          for (int x = 0; x< 1000; x++) client.print(testStr);
          client.print("Bytes sent: ");
          client.println(1000L*strlen(testStr));
          client.print("Time used:  ");
          client.print((millis()-time)/1000.0,3);
          client.println(" seconds");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }
}

Perhaps your way of doing the timing does slow down the data transfer?

When using a test string which is twice as long, I even can see as a result:

Bytes sent: 92000
Time used:  1.572 seconds

The bigger you can create the network packets (within the maximum allowed network packet length), the less network packets need to be sent and the higher the data rate you can observe.

Hmmmm.... Not sure what was going on when I ran the test yesterday. I'm now getting almost exactly what Jurs is getting - ~46Kbytes/second. That is good news.

But, EthernetClient.connected() still doesn't appear to work - always returns false. Does it work for you guys?

Regards,
Ray L.