Memory consumption of esp32 WiFi.h

I have this ultra-simple sketch:

#include <WiFi.h>

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

When I verify or upload this (with the ESP32-S3 Dev Board v3.1.0 selected), an alarming 860692 bytes of program storage are consumed.

If I comment out the #include at line 1 and re-verify, "only" 318040 bytes are consumed.

Either of these, to me, seems excessive overhead, but 500K for WiFi seems beyond ridiculous. With that and a couple of other libraries, we're out of memory before we even add any code.

I also tried this with the latest (3.3.7) version of esp32 by Espressif board. Results with and without WiFi were 836272 and 308492 respectively. So a slight improvement but still troublesome.

What, if anything (short of not using WiFi), can be done about this incredible overhead?

Try loading a WiFi sample program. I just did the Scan sample and the usage is only 64%

An S3 could have 8MB or 16MB of flash. So what's the problem in using 1MB of that.
Pick a different partition scheme if you're worried about running out of memory.
Leo..

Memory is cheap in 2026 and Wi-Fi is a complex protocol. Complex things take lots of space.

The first problem is that some specialty boads (like the one I'm using for this project, which needs to access internet to get time and other hings) are not so. The second, frankly, is that the concept that 500MB wasted unnecessarily is no big deal. It's huge, actually.

Was - memory prices have doubled in the last few months due to AI hype. They probably won't go down until the AI bubble bursts.

I think you're off by 3 orders of magnitude, KB perhaps?

Anyway, have you confirmed that there's actually a memory capacity problem accommodating the code for your intended application? Or, are you fixating on a non-existent problem?

Yes, 500 K. My bad. Does not change the facts and, yes, I have run into a problem because of excessive cost of this library. I'm trying to develop a clock that synchronizes itself with an NTP server, very little code involved in all of that. But when I added WFiManager library in place of WiFi library, memory was overflowed. And so much more needs to be done.

What problem.
It seems to have 16MB of flash. I just finished a clock (NTP) with an 8MB ESP32-S3 with four tft displays connected. The ESP32-S3 has about 30 240x240 RGB565 picures stored in SPIFFS, with still several MB spare.

Which partition scheme did you select.
You can always create your own if you don't like the default options.
Let us know if you need help with that.
Leo..

P.S.
Don't make the mistake of following outdated NTP guides that add more time libraries.
NTP time is already built into the ESP core.
It only requires one line in setup(), no libraries.

kB.

How do you know it’s unnecessary? What would you do to optimize it?

I very much doubt that that affects the cost of Flash memory on embedded processors.

@cedarlakeinstruments Can we get back on track? Did you even read the question, which I shall repeat for you here? "What, if anything, can be done about this incredible overhead?"

No, I did NTP "the esp32 way." I will post my code when back at home. I don't know about partitioning - I am a newbie (with 50+ years of programming and system design experience, Arduino is novel for me now). I will look into partition schemes and how to take advantage of such. Thanks for the tip. And, yes, if you think there's a particular resource I should investigate, I would certainly appreciate a link.

The default partition setting for your AMOLED ESP is 3MB for the sketch, of which you only use 1MB. Not a problem if unused code just sits there.
Default SPIFFS (for images) is almost 10MB (20 466x466 RGB565 images), so I don't see a problem with that either.
Leo..

In the IDE, tools>Partition Scheme gets you to the partition selector.
Make sure you have selected the AMOLED board (16MB), not just anry S3 board.

ESPConnect is a great tool to see what's under the hood and to edit SPIFFS content.
Partition Builder (advanced) can be used to create your own scheme (if needed).

For comparison, flash usage for a few board platforms; empty sketch, adding #include <WiFi.h> or <ESP8266WiFi.h>, and then WiFi.begin("","")

empty #include begin diff
Uno WiFi Rev2 1214 6052 7358 6144
ESP8266 231620 231620 234544 2924
Uno R4 53168 53504 57796 4628
ESP32 v2 232209 240325 637433 405224
ESP32 v3 297777 872201 872253 574476

I happen to have M5Stack installed, which is a fork of v2. Same board, AtomS3, on official esp32 v3.0.7 (haven't updated in a while)

R4 uses ESP32-S3 for its WiFi, but there's also firmware for R4 that deals with the WiFi.

Note that the Uno WiFi Rev2 and Uno R4 have a separate processor to handle wireless, so you do not see much of the code.

The difference between the ESP32 v2 and v3 is very substantial, possibly a problem with the library?

This is my stake in the ground. The "state of the art" at the time I made the original posting. Bear in mind, that means I knew (still true but I'm about to investigate) nothing about partitioning and options in that area. The code:

#define USE_WIFI_MANAGER


#include <lvgl.h>
#include "Arduino_GFX_Library.h"
#include "pin_config.h"
#include "lv_conf.h"
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorPCF85063.hpp"
#ifdef USE_WIFI_MANAGER
#include <WiFiManager.h>
#else
#include <WiFi.h>
#endif
#include <time.h>
#include "secrets.h"


#define EXAMPLE_LVGL_TICK_PERIOD_MS 2

static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[LCD_WIDTH * LCD_HEIGHT / 10];

lv_obj_t *label;  // Global label object
SensorPCF85063 rtc;
uint32_t lastMillis;

Arduino_DataBus *bus = new Arduino_ESP32QSPI(
  LCD_CS /* CS */, LCD_SCLK /* SCK */, LCD_SDIO0 /* SDIO0 */, LCD_SDIO1 /* SDIO1 */,
  LCD_SDIO2 /* SDIO2 */, LCD_SDIO3 /* SDIO3 */);

Arduino_CO5300 *gfx = new Arduino_CO5300(
  bus, LCD_RESET /* RST */, 0 /* rotation */, LCD_WIDTH /* width */, LCD_HEIGHT /* height */, 6, 0, 0, 0);

#if LV_USE_LOG != 0
/* Serial debugging */
void my_print(const char *buf) {
  Serial.printf(buf);
  Serial.flush();
}
#endif

void example_lvgl_rounder_cb(struct _lv_disp_drv_t *disp_drv, lv_area_t *area)
{
    if(area->x1 % 2 !=0)area->x1--;
    if(area->y1 % 2 !=0)area->y1--;
    // 变为奇数(如果是偶数就加 1)
    if(area->x2 %2 ==0)area->x2++;
    if(area->y2 %2 ==0)area->y2++;
}


/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
  uint32_t w = (area->x2 - area->x1 + 1);
  uint32_t h = (area->y2 - area->y1 + 1);

#if (LV_COLOR_16_SWAP != 0)
  gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#else
  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#endif

  lv_disp_flush_ready(disp);
}

void example_increase_lvgl_tick(void *arg) {
  /* Tell LVGL how many milliseconds has elapsed */
  lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
}

static uint8_t count = 0;
void example_increase_reboot(void *arg) {
  count++;
  if (count == 30) {
    esp_restart();
  }
}

void setup() {
  struct tm timeinfo ;
  Serial.begin(115200); /* prepare for possible serial debug */
  while (! Serial) {} // Wait for serial connection
  if (!rtc.begin(Wire, IIC_SDA, IIC_SCL)) {
    Serial.println("Failed to find PCF8563 - check your wiring!");
    while (1) {
      delay(1000);
    }
  }


#ifdef USE_WIFI_MANAGER
  WiFiManager wm ;
  if ( ! wm.autoConnect("DennisClock")) {
    Serial.println("Failed to connect before timeout.") ;
    ESP.restart() ;
  }
#else
  /* WiFi stuff... */
  Serial.println(sprintf("Connecting to WiFi %s", WIFI_SSID)) ;
  WiFi.begin(WIFI_SSID, WIFI_PASS) ;
  while (WiFi.status() != WL_CONNECTED) {
    delay(500) ;
    Serial.print(".") ;
  }
  Serial.print("\nStation connected at IP address ") ;
  Serial.println(WiFi.localIP()) ;
#endif
  configTime(LOCALTIME_GMT_OFFSET, LOCALTIME_DST_ADJ, NTP_SERVER) ;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to get local time.") ;
    while (true) delay(1000) ;
  }
  /* End WiFi stuff */

  rtc.setDateTime(timeinfo.tm_year, timeinfo.tm_mon+1, timeinfo.tm_mday
                , timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);

  gfx->begin();
  gfx->setBrightness(255);

  String LVGL_Arduino = "Hello Arduino! ";
  LVGL_Arduino += String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();

  Serial.println(LVGL_Arduino);
  Serial.println("I am LVGL_Arduino");

  lv_init();

#if LV_USE_LOG != 0
  lv_log_register_print_cb(my_print); /* register print function for debugging */
#endif


  lv_disp_draw_buf_init(&draw_buf, buf, NULL, LCD_WIDTH * LCD_HEIGHT / 10);

  /*Initialize the display*/
  static lv_disp_drv_t disp_drv;
  lv_disp_drv_init(&disp_drv);
  /*Change the following line to your display resolution*/
  disp_drv.hor_res = LCD_WIDTH;
  disp_drv.ver_res = LCD_HEIGHT;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.rounder_cb = example_lvgl_rounder_cb;
  disp_drv.draw_buf = &draw_buf;
  disp_drv.sw_rotate = 1 ;
  disp_drv.rotated = LV_DISP_ROT_NONE ;
  lv_disp_drv_register(&disp_drv);

  /*Initialize the (dummy) input device driver*/
  static lv_indev_drv_t indev_drv;
  lv_indev_drv_init(&indev_drv);
  indev_drv.type = LV_INDEV_TYPE_POINTER;
  lv_indev_drv_register(&indev_drv);

  // lv_obj_t *label = lv_label_create(lv_scr_act());
  // lv_label_set_text(label, "Hello Ardino and LVGL!");
  // lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);

  const esp_timer_create_args_t lvgl_tick_timer_args = {
    .callback = &example_increase_lvgl_tick,
    .name = "lvgl_tick"
  };

  const esp_timer_create_args_t reboot_timer_args = {
    .callback = &example_increase_reboot,
    .name = "reboot"
  };

  esp_timer_handle_t lvgl_tick_timer = NULL;
  esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer);
  esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000);

  label = lv_label_create(lv_scr_act());
  lv_label_set_text(label, "Initializing...");
  lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
}

void loop() {
  int priorRotValue = -1 ;
  lv_timer_handler(); /* let the GUI do its work */
  delay(5);

  if (millis() - lastMillis > 1000) {
    lastMillis = millis();
    RTC_DateTime datetime = rtc.getDateTime();

    char buf[32];
    #undef MONTH_NAME
    #ifdef MONTH_NAME
    const char *monthNames[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"} ;
    /*******************************************************************************************
       I get a runtime error (below) when I try to use this code.
          Guru Meditation Error: Core  / panic'ed (Cache disabled but cached memory region accessed). 
          Write back error occurred while dcache tries to write back to flash
          The following backtrace may not indicate the code that caused Cache invalid access

          Guru Meditation Error: Core  0 panic'ed (Unhandled debug exception). 
          Debug exception reason: Stack canary watchpoint triggered (IDLE0) 
          Core  0 register dump:
          PC      : 0x40056f60  PS      : 0x00060536  A0      : 0x82033e56  A1      : 0x3fcbe580  
          A2      : 0x3fcbe590  A3      : 0x3c0fcd28  A4      : 0x00000060  A5      : 0x3fcbe590  
          A6      : 0x3c0d2c52  A7      : 0x3c0d2c5b  A8      : 0x00000000  A9      : 0x00000001  
          A10     : 0x60000000  A11     : 0x0000000a  A12     : 0x82033626  A13     : 0x40376cb8  
          A14     : 0x00000000  A15     : 0x3fcbe9b4  SAR     : 0x0000000a  EXCCAUSE: 0x00000001  
          EXCVADDR: 0x00000000  LBEG    : 0x40056f5c  LEND    : 0x40056f72  LCOUNT  : 0x00000005  

          Backtrace: 0x40056f5d:0x3fcbe580 0x42033e53:0x3fcbe590 0x42033bad:0x3fcbe610 0x42033bd9:0x3fcbe630 0x4203301b:0x3fcbe650 0x4202e790:0x3fcbe680 0x42033b59:0x3fcbe6a0 0x403769a1:0x3fcbe6f0 0x40376cf4:0x3fcbe710 0x00040022:0x3fcbe7d0 |<-CORRUPTED

          Core  1 register dump:
          PC      : 0x420048ac  PS      : 0x00060034  A0      : 0x820c0851  A1      : 0x3fcc2250  
          A2      : 0x3c0e2e80  A3      : 0x3fca8704  A4      : 0x0000000c  A5      : 0x3fca8770  
          A6      : 0x3fca8574  A7      : 0x3fca73d0  A8      : 0x00001876  A9      : 0x3fcc2230  
          A10     : 0x3fca8574  A11     : 0x00014d44  A12     : 0x00000000  A13     : 0x00000006  
          A14     : 0x3fca73d0  A15     : 0x3fca876c  SAR     : 0x00000020  EXCCAUSE: 0x00000007  
          EXCVADDR: 0x00000000  LBEG    : 0x400570e8  LEND    : 0x400570f3  LCOUNT  : 0xffffffff  

          Backtrace: 0x420048a9:0x3fcc2250 0x420c084e:0x3fcc2270 0x420c0841:0x3fcc2290 0x4200563c:0x3fcc22b0 0x42022a9f:0x3fcc22d0 0x42002713:0x3fcc22f0 0x4202fcdb:0x3fcc2390 0x4037ed7a:0x3fcc23b0

          ELF file SHA256: 38d9b4e65

          Rebooting...
    ***********************************************************************/
    snprintf(buf, sizeof(buf), "%s %d, %d\n%02d:%02d:%02d"
              , monthNames[datetime.getMonth()]
              , datetime.getDay(), datetime.getYear()
              , datetime.getHour(), datetime.getMinute(), datetime.getSecond()
                  );
    #else
    snprintf(buf, sizeof(buf), "%02d/%02d/%04d\n%02d:%02d:%02d"
              , datetime.getMonth()
              , datetime.getDay(), datetime.getYear()
              , datetime.getHour(), datetime.getMinute(), datetime.getSecond()
                  );
    #endif

    // Update label with current time
    lv_label_set_text(label, buf);
    lv_obj_set_style_text_font(label, &lv_font_montserrat_48, LV_PART_MAIN);
    lv_disp_rot_t rotValue = LV_DISP_ROT_270 ;
    if (rotValue != priorRotValue) {
      priorRotValue = rotValue ;
      lv_disp_set_rotation(NULL, (lv_disp_rot_t) rotValue) ;
    }
  }
  delay(20);
}


The file "secrets.h"'


```cpp
#define WIFI_SSID "still.secret"
#define WIFI_PASS "more secret"
#define LOCALTIME_GMT_OFFSET -18000
#define LOCALTIME_DST_ADJ 3600
#define NTP_SERVER "pool.ntp.org"

The result:

Sketch uses 1387792 bytes (105%) of program storage space. Maximum is 1310720 bytes.
Global variables use 139468 bytes (42%) of dynamic memory, leaving 188212 bytes for local variables. Maximum is 327680 bytes.
Sketch too big; see https://support.arduino.cc/hc/en-us/articles/360013825179 for tips on reducing it.
text section exceeds available space in board

Compilation error: text section exceeds available space in board

Now I've received a good deal of advice above, which I am about to pore through. The offhand comments in the above I will try (beyond this statement) to ignore with thick skin. Probably attributable to a bad day. Thank you, thank you to those of you who have provided and offered help.

Some of what I've read ("default partition setting ... is 3MB", for example) don't seem to apply in my case, and some things I don't understand (e.g. same post: "Make sure you have selected AMOLED...") but give me some time - I will try to make sense of all your help.

Again, I truly appreciate the attention. Now let's see if I can learn sump'n.

Why the RTC and the time library. Is this clock portable or outside your WiFi area.
The ESP holds perfect time within the default 3-hourly NTP updates.

I don't think the (4MB) "ESP32S3 Dev Module" is the right board choice.
There are several 16MB Waveshare AMOLED options in the boards selector.


The one I randomly picked had a default 3MB sketch option instead of the 1.2Mb that gave you trouble.
Leo..

Thanks, Leo. Most of this code (I only added WiFi and rotation and some cosmetic stuff) is directly from Waveshare's sample sketch 03_...*...SimpleTime. All of the rtc code is theirs. I don't really know how much of it I need, but had some (unearned?) confidence that the sample didn't include anything unnecessary.

Also, I chose the DevBoard because the 1.75" wax not listed and I don't find a feature comprison chart to make an intelligent choice. Plus I don't know what I'm doing.

This command, with location string, does it all in one line.

// https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
configTzTime("NZST-12NZDT,M9.5.0,M4.1.0/3", "nz.pool.ntp.org");

Leo..