Skip to content

ESP32-S2 web OTA idle performance question #6009

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
snico2 opened this issue Dec 11, 2021 · 14 comments
Closed

ESP32-S2 web OTA idle performance question #6009

snico2 opened this issue Dec 11, 2021 · 14 comments
Labels
Area: Performance Issue related to performance problems and improvements Chip: ESP32-S2 Issue is related to support of ESP32-S2 Chip Status: Solved Type: Question Only question

Comments

@snico2
Copy link

snico2 commented Dec 11, 2021

Hi everyone,
I have noticed strange behavior of the web OTA software (in idle state) between the ESP8266 and ESP32-S2 chips.

I performed a series of 4 tests on the same incremental code to measure the time taken to execute 500,000 Main Loop cycles and calculate the relative speed.

The boards used are:

ESP-01S with chip ESP8266 single-core Tensilica L106 80 MHz
LOLIN S2 Mini with chip ESP32-S2 Single-core Xtensa LX7 240 MHz

Considering the characteristics of the chips as a result of the tests I expect a much higher speed of the ESP32-S2 chip.

The tests were performed on 4 sketch adding a new functionality to each one.

  1. In the first test the MainLoop was empty without defining and calling other libraries.
    ESP32-S2 was 5.6 times faster than ESP8266

  2. In the second test the definition of the Wifi library was added and the connection to the network, the MainLoop was not changed.
    ESP32-S2 was 5.6 times faster than ESP8266

  3. In the third test, WebServer, HTTPUpdateServer and WiFiClient libraries were added for the web OTA functionality.
    In the mainLoop the call to the "handleClient()" function has been added.
    Surprise, ESP8266 was 79.8 times faster than ESP32-S2 !!!

  4. The fourth test was performed only for ESP32, adding the call to "enableDelay(false)" first of the "handleClient()"
    ESP8266 was 1.2 times faster than ESP32-S2 only

Why is ESP32-S2 even slower than ESP8266?
Is there something still to be optimized in the web OTA library?

Thanks.

Test summary with Value Average:

------------------------------------------------------------------------------
                         ESP8266 80 MHz              ESP32-S2 240 MHz                
LoopCode                LoopTime    Speed           LoopTime    Speed   
------------------------------------------------------------------------------
1) Empty                4699 ms     106405 c/s        839 ms    595947 c/s      
2) Only Wifi            4730 ms     105708 c/s        842 ms    593824 c/s      
3) Wifi+OTA             6278 ms      79642 c/s     501268 ms       997 c/s      
4) Wifi+OTA no Delay                                 7425 ms     67340 c/s      
------------------------------------------------------------------------------

SpeedTest1.ino code

/***************************************************************
 *  SpeedTest1
 ***************************************************************/ 

#define LED_GPIO               15
#define UART_RATE          115200UL
#define WAIT_CYCLES        500000UL
#define CYCLES_SEC      500000000UL

uint32_t loopCount;
uint32_t loopBegin;
uint32_t loopTime;
uint32_t loopSpeed;

/***************************************************************
 *  Calculate loop cycles speed
 ***************************************************************/ 
void speedLoop() {
    digitalWrite(LED_GPIO, HIGH);
    loopCount++;
    if (loopCount < WAIT_CYCLES) return;
    loopTime = millis() - loopBegin;                // ms consumed for 500.000 loop
    loopSpeed = CYCLES_SEC / loopTime; 
    Serial.print("LoopTime: ");
    Serial.print(loopTime);
    Serial.println(" ms");
    Serial.print("Speed: ");
    Serial.print(loopSpeed);
    Serial.println(" c/s");
    loopCount = 0;                                  // Start new count
    loopBegin = millis();        
}

/***************************************************************
 *  Setup procedure
 ***************************************************************/ 
void setup() {
    pinMode(LED_GPIO, OUTPUT);
    Serial.begin(UART_RATE);
    Serial.println("SPEED TEST");
    loopCount = 0;
    loopBegin = millis();        
}

/***************************************************************
 *  Main loop
 ***************************************************************/ 
void loop() {
    speedLoop();
}

SpeedTest2.ino code

/***************************************************************
 *  SpeedTest2
 ***************************************************************/ 

#if defined ESP8266
    #include <ESP8266WiFi.h>
#endif
#if defined ESP32
    #include <WiFi.h>
#endif
#include <Arduino.h>

#define LED_GPIO               15
#define UART_RATE          115200UL
#define WAIT_CYCLES        500000UL
#define CYCLES_SEC      500000000UL

#define WIFI_SSID       "mySsid"
#define WIFI_PSK        "myPsk"

uint32_t loopCount;
uint32_t loopBegin;
uint32_t loopTime;
uint32_t loopSpeed;

/***************************************************************
 *  Init Wifi STA mode
 ***************************************************************/ 
bool initWifiSTA(uint8_t sec) {
uint32_t timeStart;
uint32_t timeOut;

    WiFi.disconnect(true); 
    WiFi.persistent(false);
    Serial.println("Attempting WIFI connection: STA mode");
    WiFi.mode(WIFI_STA);
    WiFi.begin(WIFI_SSID, WIFI_PSK);

    timeStart = millis();
    timeOut = 1000 * sec;

    while (WiFi.status() != WL_CONNECTED) {
        if (millis() - timeStart > timeOut) {
            Serial.println();
            Serial.println("ERRROR to wifi connection");
            return false;
        }
        delay(200);
        Serial.print(".");
    }
    Serial.println();
    Serial.println("Connected to wifi network");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    return true;
}

/***************************************************************
 *  Calculate loop cycles speed
 ***************************************************************/ 
void speedLoop() {
    digitalWrite(LED_GPIO, HIGH);
    loopCount++;
    if (loopCount < WAIT_CYCLES) return;
    loopTime = millis() - loopBegin;                // ms consumed for 500.000 loop
    loopSpeed = CYCLES_SEC / loopTime; 
    Serial.print("LoopTime: ");
    Serial.print(loopTime);
    Serial.println(" ms");
    Serial.print("Speed: ");
    Serial.print(loopSpeed);
    Serial.println(" c/s");
    loopCount = 0;                                  // Start new count
    loopBegin = millis();        
}

/***************************************************************
 *  Setup procedure
 ***************************************************************/ 
void setup() {
    pinMode(LED_GPIO, OUTPUT);
    Serial.begin(UART_RATE);
    Serial.println("SPEED TEST");
    loopCount = 0;
    loopBegin = millis();        
    initWifiSTA(20);
}

/***************************************************************
 *  Main loop
 ***************************************************************/ 
void loop() {
    speedLoop();
}

SpeedTest3.ino code

/***************************************************************
 *	SpeedTest3
 ***************************************************************/

#if defined ESP8266
    #include <ESP8266WiFi.h>
    #include <ESP8266WebServer.h>
    #include <ESP8266HTTPUpdateServer.h>
#endif
#if defined ESP32
    #include <WiFi.h>
    #include <WebServer.h>
    #include <HTTPUpdateServer.h>
#endif
#include <WiFiClient.h>
#include <Arduino.h>

#define LED_GPIO			   15
#define UART_RATE		   115200UL
#define WAIT_CYCLES		   500000UL
#define CYCLES_SEC		500000000UL

#define HTTP_PORT       8080
#define WIFI_SSID       "mySsid"
#define WIFI_PSK        "myPsk"
#define USER_NAME       "admin"
#define USER_PWD        "admin"
#define HTTP_PATH_LOAD  "/firmware"

#if defined ESP8266
	ESP8266WebServer httpServer(HTTP_PORT);
	ESP8266HTTPUpdateServer httpUpdater;
#endif

#if defined ESP32
	WebServer httpServer(HTTP_PORT);
	HTTPUpdateServer httpUpdater;
#endif

uint32_t loopCount;
uint32_t loopBegin;
uint32_t loopTime;
uint32_t loopSpeed;

/***************************************************************
 *	Init Wifi STA mode
 ***************************************************************/
bool initWifiSTA(uint8_t sec) {
uint32_t timeStart;
uint32_t timeOut;

    WiFi.disconnect(true);
    WiFi.persistent(false);
    Serial.println("Attempting WIFI connection: STA mode");
   	WiFi.mode(WIFI_STA);
	WiFi.begin(WIFI_SSID, WIFI_PSK);

	timeStart = millis();
	timeOut = 1000 * sec;

	while (WiFi.status() != WL_CONNECTED) {
   		if (millis() - timeStart > timeOut) {
   			Serial.println();
   			Serial.println("ERRROR to wifi connection");
   			return false;
		}
		delay(200);
   		Serial.print(".");
	}
	Serial.println();
	Serial.println("Connected to wifi network");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
	return true;
}

/***************************************************************
 *	Loop for http request
 ***************************************************************/
void httpLoop() {
    httpServer.handleClient();
}

/***************************************************************
 *	Calculate loop cycles speed
 ***************************************************************/
void speedLoop() {
    digitalWrite(LED_GPIO, HIGH);
    loopCount++;
    if (loopCount < WAIT_CYCLES) return;
	loopTime = millis() - loopBegin;                // ms consumed for 500.000 loop
    loopSpeed = CYCLES_SEC / loopTime;
    Serial.print("LoopTime: ");
    Serial.print(loopTime);
    Serial.println(" ms");
    Serial.print("Speed: ");
    Serial.print(loopSpeed);
    Serial.println(" c/s");
    loopCount = 0;                                  // Start new count
    loopBegin = millis();
}

/***************************************************************
 *	Setup procedure
 ***************************************************************/
void setup() {
	pinMode(LED_GPIO, OUTPUT);
	Serial.begin(UART_RATE);
	Serial.println("SPEED TEST");
    loopCount = 0;
  	loopBegin = millis();
	initWifiSTA(20);
  	httpUpdater.setup(&httpServer, HTTP_PATH_LOAD, USER_NAME, USER_PWD);
  	httpServer.begin(HTTP_PORT);
}

/***************************************************************
 *	Main loop
 ***************************************************************/
void loop() {
    httpLoop();     
    speedLoop();
}

SpeedTest4.ino code

/***************************************************************
 *  SpeedTest4
 ***************************************************************/ 

#if defined ESP8266
    #include <ESP8266WiFi.h>
    #include <ESP8266WebServer.h>
    #include <ESP8266HTTPUpdateServer.h>
#endif
#if defined ESP32
    #include <WiFi.h>
    #include <WebServer.h>
    #include <HTTPUpdateServer.h>
#endif
#include <WiFiClient.h>
#include <Arduino.h>

#define LED_GPIO               15
#define UART_RATE          115200UL
#define WAIT_CYCLES        500000UL
#define CYCLES_SEC      500000000UL

#define HTTP_PORT       8080
#define WIFI_SSID       "mySsid"
#define WIFI_PSK        "myPsk"
#define USER_NAME       "admin"
#define USER_PWD        "admin"
#define HTTP_PATH_LOAD  "/firmware"

#if defined ESP8266
    ESP8266WebServer httpServer(HTTP_PORT);
    ESP8266HTTPUpdateServer httpUpdater;
#endif

#if defined ESP32
    WebServer httpServer(HTTP_PORT);
    HTTPUpdateServer httpUpdater;
#endif

uint32_t loopCount;
uint32_t loopBegin;
uint32_t loopTime;
uint32_t loopSpeed;

/***************************************************************
 *  Init Wifi STA mode
 ***************************************************************/ 
bool initWifiSTA(uint8_t sec) {
uint32_t timeStart;
uint32_t timeOut;

    WiFi.disconnect(true); 
    WiFi.persistent(false);
    Serial.println("Attempting WIFI connection: STA mode");
    WiFi.mode(WIFI_STA);
    WiFi.begin(WIFI_SSID, WIFI_PSK);

    timeStart = millis();
    timeOut = 1000 * sec;

    while (WiFi.status() != WL_CONNECTED) {
        if (millis() - timeStart > timeOut) {
            Serial.println();
            Serial.println("ERRROR to wifi connection");
            return false;
        }
        delay(200);
        Serial.print(".");
    }
    Serial.println();
    Serial.println("Connected to wifi network");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    return true;
}


/***************************************************************
 *  Loop for http request
 ***************************************************************/ 
void httpLoop() {
    #if defined ESP32
        httpServer.enableDelay(false);
    #endif
    httpServer.handleClient();
}


/***************************************************************
 *  Calculate loop cycles speed
 ***************************************************************/ 
void speedLoop() {
    digitalWrite(LED_GPIO, HIGH);
    loopCount++;
    if (loopCount < WAIT_CYCLES) return;
    loopTime = millis() - loopBegin;                // ms consumed for 500.000 loop
    loopSpeed = CYCLES_SEC / loopTime; 
    Serial.print("LoopTime: ");
    Serial.print(loopTime);
    Serial.println(" ms");
    Serial.print("Speed: ");
    Serial.print(loopSpeed);
    Serial.println(" c/s");
    loopCount = 0;                                  // Start new count
    loopBegin = millis();        
}


/***************************************************************
 *  Setup procedure
 ***************************************************************/ 
void setup() {
    pinMode(LED_GPIO, OUTPUT);
    Serial.begin(UART_RATE);
    Serial.println("SPEED TEST");
    loopCount = 0;
    loopBegin = millis();        
    initWifiSTA(20);
    httpUpdater.setup(&httpServer, HTTP_PATH_LOAD, USER_NAME, USER_PWD);
    httpServer.begin(HTTP_PORT);    
}


/***************************************************************
 *  Main loop
 ***************************************************************/ 
void loop() {
    httpLoop();     
    speedLoop();
}
@Miraculix200
Copy link

Miraculix200 commented Dec 11, 2021

In the third test, WebServer, HTTPUpdateServer and WiFiClient libraries were added for the web OTA functionality.
In the mainLoop the call to the "handleClient()" function has been added.
Surprise, ESP8266 was 79.8 times faster than ESP32-S2 !!!

What happens when you add delay(1); in the main loop? I had a similar problem with the webserver on the ESP32-S2 a year ago or so. Not sure if it's still fixed, or the fix has been reverted. If that makes it faster, the problem is the webserver, not OTA.

@snico2
Copy link
Author

snico2 commented Dec 11, 2021

The purpose of the sketch was to measure the speed of the mainloop. By adding the delay (1) in the mainloop the starting speed decreases.
In any case, the firmware update via the web OTA always works with and without the delay.

@Miraculix200
Copy link

A year ago, adding delay(1); to the loop significantly reduced the response time by the webserver.

@snico2
Copy link
Author

snico2 commented Dec 11, 2021

With delay(1) inside SpeeTest3 the speed is:
LoopTime: 1008800 ms
Speed: 495 c/s

This because httpServer.handleClient() already has a delay(1) ...

WebServer.cpp

void WebServer::handleClient() {
  if (_currentStatus == HC_NONE) {
    WiFiClient client = _server.available();
    if (!client) {
      if (_nullDelay) {
        delay(1);
      }
      return;
    }

@Jason2866
Copy link
Collaborator

Being curios what results do you get with a ESP32?

@snico2
Copy link
Author

snico2 commented Dec 12, 2021

Sorry, i don't have ESP32 chip.
You can copy speedtest code for a test ...

@VojtechBartoska VojtechBartoska added the Chip: ESP32-S2 Issue is related to support of ESP32-S2 Chip label Dec 13, 2021
@GiovanniCmpaner
Copy link

If you are after performance, I would take a look at:
https://github.com/me-no-dev/ESPAsyncWebServer
It's an async webserver with lots of features, you would still be able to implement an OTA handling.
Even then, when using with ESP32-S2, you would need to add a delay(1) in the main loop().

@VojtechBartoska VojtechBartoska added the Area: Performance Issue related to performance problems and improvements label Dec 20, 2021
@VojtechBartoska VojtechBartoska added Type: Question Only question Resolution: Awaiting response Waiting for response of author labels Apr 11, 2022
@VojtechBartoska
Copy link
Contributor

Hello @snico2, can I consider this as answered?

@snico2
Copy link
Author

snico2 commented Apr 11, 2022

Hi, yes

@VojtechBartoska VojtechBartoska added Status: Solved and removed Resolution: Awaiting response Waiting for response of author labels Apr 11, 2022
@scottchiefbaker
Copy link

@snico2 did you get this resolved? I'm running in to the same thing here. Essentially all my ESP32 projects that use WebServer.h are significantly slower than the ESP8266.

@Jason2866
Copy link
Collaborator

Jason2866 commented Mar 9, 2023

@scottchiefbaker
Copy link

I believe this is the same issue as #7708.

@snico2
Copy link
Author

snico2 commented Mar 11, 2023

Hi i have repeat the test with other Board/Chip.

ESP32 is always slower than ESP8266 even without the Delay(1).

But using the old version ESP32 Arduino 1.06 the execution time improves a lot using httpServer.enableDelay(false).

Using Delay(1) the v1.06 it has the same tempo as v2.07

SpeedTest-4 with httpServer.enableDelay(false);

CHIP ESP32 240 MHz
BOARD DevKit C v4
SDK v2.07
LoopTime: 1425 ms
Speed: 35087 c/s

CHIP ESP32-S3 240 MHz
BOARD M5-Stack S3
SDK v2.07
LoopTime: 899 ms
Speed: 55617 c/s

CHIP ESP32 240 MHz
BOARD DevKit C v4
SDK v1.06
LoopTime: 698 ms
Speed: 71633 c/s

SpeedTest-3 without httpServer.enableDelay(false);

CHIP ESP8266 80 MHz
BOARD ESP-01S
SDK v3.02
LoopTime: 626 ms
Speed: 79872 c/s

CHIP ESP32 240 MHz
BOARD DevKit C v4
SDK v1.06
LoopTime: 50000 ms
Speed: 1000 c/s

CHIP ESP32 240 MHz
BOARD DevKit C v4
SDK v2.06
LoopTime: 50005 ms
Speed: 999 c/s

in summary, httpServer.enableDelay(false) improves times but does not solve the problem

@scottchiefbaker
Copy link

@snico2 check out #7708 I put some more details there because it's the same issue and it's still open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Performance Issue related to performance problems and improvements Chip: ESP32-S2 Issue is related to support of ESP32-S2 Chip Status: Solved Type: Question Only question
Projects
None yet
Development

No branches or pull requests

6 participants