esphome
esphome copied to clipboard
Disable Ethernet loop polling when connected and stable
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:
- [ ] Documentation added/updated in esphome-docs.
[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
I think we need to enable the loop using the ISR safe helper since the ethernet callbacks happen in a different task AFAICT