Ethernet client.connected seems very slow on Portenta H7

Hello I'm building a project that makes a connection to Processing application, I need to send a message from processing (e.g. "read") and send it via ethernet/wifi to my Arduino, process it and send a response back to the app. When doing so I noticed that since I send the message, until I receive the response the time seems to be about 125ms, a closer inspection revealed that most of the time is spent in the client.connected() instruction.

I'm using a Portenta H7 with the Portenta Breakout Board

#include <PortentaEthernet.h>
#include <Ethernet.h>

bool NDR = false;
EthernetServer server(10932);
String dataRec = "";
byte mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
bool new_data_in = false;

void setup() {
  Serial.begin(115200);
    while (!Serial) {
      ; // wait for serial port to connect.
    }
  while(!Ethernet.begin(mac)){ //Begin Ethernet with DHCP
    delay(1000);
    Serial.println("...");
  }

  server.begin();

}

void loop() {
  EthernetClient client = server.available();
  client.setTimeout(50);
  if (client) {
    unsigned long int time_a = millis();
    while(client.connected()) {
      
      if(client.available() > 0) {
        char c = client.read();
        dataRec += c;
        new_data_in = true;
      }
      
      if(client.available() <= 0 && new_data_in == true){
        new_data_in = false;
        NDR = true;
        unsigned long int time_b = millis();
        printDelta(time_a, time_b, "time_a", "time_b");
      }
      
      if(NDR){
        client.print(dataRec);
        dataRec = "";
      }
    }
    // close the connection:
    client.stop();
  }
}

void printDelta(unsigned long int start_time, unsigned long int end_time, String start_name, String end_name){
  Serial.print("It took ");
  Serial.print(end_time - start_time);
  Serial.print(" ms from ");
  Serial.print(start_name);
  Serial.print(" to ");
  Serial.println(end_name);
}

the output says:

It took 105 ms from time_a to time_b

How can I make the code faster or more efficient?, Is there any change I can make even if it is to the library? 100ms is way too much and a dealbreaker If I can't make it faster. I hope I'm doing something wrong and has nothing to do with the library...

Edit: I ran the same sketch adding the SPI library and CS pin on an Arduino UNO with an ethernet Shield.

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

bool NDR = false;
EthernetServer server(10932);
String dataRec = "";
byte mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
bool new_data_in = false;

void setup() {
  Ethernet.init(10);  // Most Arduino shields
  Serial.begin(115200);
    while (!Serial) {
      ; // wait for serial port to connect.
    }
  while(!Ethernet.begin(mac)){ //Begin Ethernet with DHCP
    delay(1000);
    Serial.println("...");
  }

  server.begin();
  Serial.println(Ethernet.localIP());
}

void loop() {
  EthernetClient client = server.available();
  client.setTimeout(50);
  if (client) {
    unsigned long int time_a = millis();
    while(client.connected()) {
      
      if(client.available() > 0) {
        char c = client.read();
        dataRec += c;
        new_data_in = true;
      }
      
      if(client.available() <= 0 && new_data_in == true){
        new_data_in = false;
        NDR = true;
        unsigned long int time_b = millis();
        printDelta(time_a, time_b, "time_a", "time_b");
      }
      
      if(NDR){
        client.print(dataRec);
        dataRec = "";
      }
    }
    // close the connection:
    client.stop();
  }
}

void printDelta(unsigned long int start_time, unsigned long int end_time, String start_name, String end_name){
  Serial.print("It took ");
  Serial.print(end_time - start_time);
  Serial.print(" ms from ");
  Serial.print(start_name);
  Serial.print(" to ");
  Serial.println(end_name);
}

This was the result:

It took 1 ms from time_a to time_b
It took 1 ms from time_a to time_b
It took 2 ms from time_a to time_b
It took 1 ms from time_a to time_b
It took 1 ms from time_a to time_b

HOW???

Thanks!

That's almost impossible because that method just returns a member variable of the object. It won't even wait for a status or so. How did you take that time?

That less than the 125ms you mentioned earlier and show no information about the size of the record received.

What speed did you expect?

I think the problem is there there but I don't know for sure.

The original program takes those 20-ish ms depending on stuff that goes inside the if(NDR){} statement, I forgot to mention, but those 20-ish ms are expected so I'm not taking them into account. The problem is getting the data from the ethernet buffer, in total my Processing app sends 10 characters at max. So It shouldn't take 100ms to check if they are there and get them

I expected less than 10ms, It's not that crazy, it doesn't take more than 1-2ms to read the buffer, so I don't know where those 100ms come, weird thing is that they are almost exactly 100ms every time.

I'm quite sure it isn't.

What round trip times do you have on your network?

Sniff your network and measure the time between the SYNC packet and the last packet that contains data. What does that show? How many data packets do you see?

I have 3 devices on my network, the PC where I send the messages from, the Arduino and the router.

From the SYN Flag up until the last message with data there are 100-ish ms. With the Arduino UNO there are 1-2ms

The Time from the packet with data from the PC and the response from the Portenta is 100-ish ms with no packets in between.

The Time from the packet with data from the PC and the response from the Arduino UNO is 1-2ms with no packets in between.

There are 2 data packets: One from the PC and One from the Arduino.

I edited the post and added a test with the same program with the modifications needed to run on an Arduino UNO, Please take a look. The UNO responds in 1ms.

What Else could it be? The PC App is the same, the router is the same, the program is the same, The only thing that is different is the Arduino (And the Portenta Ethernet Library)

That doesn't answer my question. If you ping your router what values do you get?

You definitely haven't sniffed the network. There are more packets to have a TCP connection established. Do actually sniff the network using a program like WireShark and attach the saved data.

BTW, you take the time from the initial connection until you read the first byte. As far as I can see that time must be spent in some mbed OS routines as the available libraries doesn't show any code that waits for something or spend time otherwise.

The router shouldn't be involved (I seriously hope so).

No, it's not only the library. With the UNO you control the hardware directly, using the datasheet and the available code you can search for every microsecond spent. The Portenta uses a multi-threading operating system where time could be spent at various places which you cannot directly control. So that's about the same as if you have such problems ona Windows PC. You won't be able to track that down completely because you never get all code involved.

Hi team! We have the same problem with no real support from Ardruino team. Please, could anyone help us? This project is very important and we have no idea how to fix it. The connection to ethernet is too slow for our purpose, other evaluation kits are really faster than this, e.g. Ardruino Mega, Due, etc.
Any idea o anything will be appreciated.
Best regards

Are you using a version of the core to >= 3.1.1?
There was some network "speed up" (remove hard coded delays...) in that release:

1 Like

yes, thanks for answering, I'm using 3.3.0, indeed those delays are not there, when I first found that github post with the hardcoded 100ms delays I thought that was it, but unfortunately the problem seems to be somewhere else. Also the Arduino support team responded me with this:

Unfortunately Arduino developers do not have allocated time to look deeper into the issue.

Sooooooooooooooo... yeah...

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.