esphome icon indicating copy to clipboard operation
esphome copied to clipboard

Disable Ethernet loop polling when connected and stable

Open bdraco opened this issue 5 months ago • 2 comments

Going to need https://github.com/esphome/esphome/pull/9127

What does this implement/fix?

This PR optimizes the Ethernet component by disabling its loop when the connection is stable, reducing unnecessary runtime overhead.

Currently, the Ethernet component's loop() method runs on every main loop iteration, even when the connection is stable and no state changes are needed. While each call is lightweight, the cumulative effect of being called thousands of times per second adds up.

The optimization uses the disable_loop() and enable_loop() methods (introduced in PR #9089) to:

  • Disable the loop when the Ethernet connection is in a stable CONNECTED state
  • Re-enable the loop immediately when the connection is lost or disconnected
  • Re-enable the loop when Ethernet is stopped or restarted
  • Keep the loop active during connection establishment to monitor the 15-second timeout

This change reduces the Ethernet component's runtime from being one of the highest consumers to nearly zero when the connection is stable.

Types of changes

  • [ ] Bugfix (non-breaking change which fixes an issue)
  • [ ] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [x] Code quality improvements to existing code or addition of tests
  • [ ] Other

Related issue or feature (if applicable):

  • Depends on #9089 being merged first

Pull request in esphome-docs with documentation (if applicable):

  • N/A - No documentation changes needed as this is an internal optimization

Test Environment

  • [x] ESP32
  • [x] ESP32 IDF
  • [ ] ESP8266
  • [ ] RP2040
  • [ ] BK72xx
  • [ ] RTL87xx

Example entry for config.yaml:

# No configuration changes needed - this is an internal optimization
ethernet:
  type: LAN8720
  mdc_pin: GPIO23
  mdio_pin: GPIO18
  clk_mode: GPIO0_IN
  phy_addr: 0

Checklist:

  • [x] The code change is tested and works locally.
  • [ ] Tests have been added to verify that the new code works (under tests/ folder).

If user exposed functionality or configuration variables are added/changed:

bdraco avatar Jun 16 '25 15:06 bdraco

[05:10:53][I][runtime:100]: Component Runtime Statistics
[05:10:53][I][runtime:101]: Period stats (last 60000ms):
[05:10:53][I][runtime:122]:   bluetooth_proxy: count=16418, avg=0.08ms, max=21ms, total=1283ms
[05:10:53][I][runtime:122]:   api: count=6511, avg=0.19ms, max=16ms, total=1205ms
[05:10:53][I][runtime:122]:   esp32_ble: count=6511, avg=0.17ms, max=18ms, total=1133ms
[05:10:53][I][runtime:122]:   esp32_ble_tracker: count=6511, avg=0.14ms, max=16ms, total=923ms
[05:10:53][I][runtime:122]:   logger: count=6511, avg=0.06ms, max=198ms, total=366ms
[05:10:53][I][runtime:122]:   esphome.ota: count=6511, avg=0.06ms, max=6ms, total=365ms
[05:10:53][I][runtime:122]:   ethernet: count=6511, avg=0.05ms, max=6ms, total=349ms
[05:10:53][I][runtime:122]:   status_led: count=6511, avg=0.03ms, max=5ms, total=172ms
[05:10:53][I][runtime:122]:   gpio.binary_sensor: count=6511, avg=0.02ms, max=3ms, total=135ms
[05:10:53][I][runtime:122]:   preferences: count=6512, avg=0.01ms, max=8ms, total=56ms
[05:10:53][I][runtime:122]:   uptime.sensor: count=1, avg=5.00ms, max=5ms, total=5ms
[05:10:53][I][runtime:122]:   homeassistant.time: count=2, avg=1.50ms, max=2ms, total=3ms
[05:10:53][I][runtime:122]:   template.sensor: count=1, avg=3.00ms, max=3ms, total=3ms
[05:10:53][I][runtime:128]: Total stats (since boot):
[05:10:53][I][runtime:140]:   esp32_ble_tracker: count=229880, avg=0.19ms, max=16ms, total=43863ms
[05:10:53][I][runtime:140]:   ethernet: count=229880, avg=0.13ms, max=189ms, total=29149ms
[05:10:53][I][runtime:140]:   api: count=229880, avg=0.12ms, max=20ms, total=27680ms
[05:10:53][I][runtime:140]:   bluetooth_proxy: count=292894, avg=0.09ms, max=27ms, total=26684ms
[05:10:53][I][runtime:140]:   esp32_ble: count=229880, avg=0.05ms, max=19ms, total=11085ms
[05:10:53][I][runtime:140]:   logger: count=229880, avg=0.04ms, max=198ms, total=8303ms
[05:10:53][I][runtime:140]:   esphome.ota: count=229880, avg=0.02ms, max=9ms, total=5547ms
[05:10:53][I][runtime:140]:   status_led: count=229881, avg=0.01ms, max=16ms, total=3087ms
[05:10:53][I][runtime:140]:   gpio.binary_sensor: count=229880, avg=0.01ms, max=16ms, total=2508ms
[05:10:53][I][runtime:140]:   preferences: count=229914, avg=0.01ms, max=18ms, total=1601ms
[05:10:53][I][runtime:140]:   homeassistant.time: count=68, avg=1.72ms, max=4ms, total=117ms
[05:10:53][I][runtime:140]:   template.sensor: count=34, avg=2.47ms, max=5ms, total=84ms
[05:10:53][I][runtime:140]:   uptime.sensor: count=34, avg=2.29ms, max=5ms, total=78ms

bdraco avatar Jun 16 '25 15:06 bdraco

I think we need to enable the loop using the ISR safe helper since the ethernet callbacks happen in a different task AFAICT

bdraco avatar Jun 18 '25 10:06 bdraco