Skip to content

esp32/boards: Raise default lwIP TCP window on PSRAM boards. - #19592

Open
pavelrevak wants to merge 1 commit into
micropython:masterfrom
pavelrevak:esp32_psram_tcp_window
Open

esp32/boards: Raise default lwIP TCP window on PSRAM boards.#19592
pavelrevak wants to merge 1 commit into
micropython:masterfrom
pavelrevak:esp32_psram_tcp_window

Conversation

@pavelrevak

Copy link
Copy Markdown
Contributor

Raises the default lwIP TCP window on esp32 boards with external PSRAM,
which currently run with a window too small to use the WiFi link.

The problem

The esp32 port uses the lwIP default TCP send buffer / window of 5760
bytes. A single TCP connection is then limited to window / RTT; at a
typical WiFi RTT of ~5 ms that caps throughput at roughly 5-10 Mbit/s
regardless of the WiFi PHY rate or band -- the extra capacity of
5 GHz / 802.11ax is wasted. The ESP32-P4 board already raises this in its
own config; other boards don't.

The fix

Set CONFIG_LWIP_TCP_SND_BUF_DEFAULT and CONFIG_LWIP_TCP_WND_DEFAULT to
65534 in sdkconfig.spiram_oct and sdkconfig.spiram_quad, covering the
S2/S3/C5 boards that use quad/octal PSRAM. It is gated on PSRAM
deliberately: the larger per-connection buffers cost internal RAM, so
non-PSRAM boards keep the small window (size over speed). The
original-ESP32 PSRAM config (sdkconfig.spiram_esp32) is left unchanged
for now -- those chips have a lower WiFi PHY and less RAM headroom and I
have not tested them; it can be a follow-up.

Testing

Raw single-connection TCP TX throughput (RSSI -40..-48 dBm). The ESP32-C5
was on an 802.11ax (WiFi 6) AP; the S3 figure is a generic ESP32-S3
module:

board before after
ESP32-C5, 2.4 GHz 9.4 31.7 Mbit/s
ESP32-C5, 5 GHz 6.6 34.7 Mbit/s
ESP32-S3 5.0 11.0 Mbit/s

The cap was confirmed window-limited (effective in-flight data ~= 5760 B,
the default), and opening several parallel connections scaled aggregate
throughput before the fix -- i.e. the WiFi PHY had headroom a single
connection could not use.

Generative AI

I used generative AI tools when creating this PR, but a human has checked the
code and is responsible for the code and the description above.

The lwIP default TCP send buffer and window (5760 bytes) limit a single
TCP connection to window/RTT, which at a typical WiFi RTT of ~5 ms caps
throughput at roughly 5-10 Mbit/s regardless of the WiFi PHY rate or
band -- the extra capacity of 5 GHz / 802.11ax is simply wasted.

Set CONFIG_LWIP_TCP_SND_BUF_DEFAULT and CONFIG_LWIP_TCP_WND_DEFAULT to
65534 in sdkconfig.spiram_oct and sdkconfig.spiram_quad, so boards with
external PSRAM get a full-size TCP window.  This is gated on PSRAM on
purpose: the larger per-connection buffers cost internal RAM, so boards
without PSRAM keep the small window (size over speed).  The ESP32-P4
board already sets this in its own config.

Measured single-connection TCP TX throughput (RSSI -40..-48 dBm).  The
ESP32-C5 was associated to an 802.11ax (WiFi 6) access point; the S3
figure is from a generic ESP32-S3 module:

  ESP32-C5, 2.4 GHz:  9.4 -> 31.7 Mbit/s
  ESP32-C5, 5 GHz:    6.6 -> 34.7 Mbit/s
  ESP32-S3:           5.0 -> 11.0 Mbit/s

Signed-off-by: Pavel Revak <pavelrevak@gmail.com>
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

Code size report:

Reference:  py/gc: Track the min/max of the entire heap area when using split heap. [5f2181f]
Comparison: esp32/boards: Raise default lwIP TCP window on PSRAM boards. [merge of 12097a9]
  mpy-cross:    +0 +0.000% 
   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:    +0 +0.000% standard
      stm32:    +0 +0.000% PYBV10
      esp32:    +0 +0.000% ESP32_GENERIC
     mimxrt:    +0 +0.000% TEENSY40
        rp2:    +0 +0.000% RPI_PICO_W
       samd:    +0 +0.000% ADAFRUIT_ITSYBITSY_M4_EXPRESS
  qemu rv32:    +0 +0.000% VIRT_RV32

@pavelrevak

Copy link
Copy Markdown
Contributor Author

This makes WiFi actually fast on PSRAM boards: a single TCP
connection goes from ~5-10 to ~30 Mbit/s (up to ~5×), just by giving lwIP
a full-size TCP window. One config line per file, no downside where
there's the RAM for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants