Skip to content

perf: pipeline recompute short-circuit (fingerprint gating _calculate_cover_state) #542

@jrhubott

Description

@jrhubott

Follow-up from #540 and the per-entity write-gating work. Layer 1 (gating redundant async_write_ha_state at AdaptiveCoverBaseEntity) and Layer 2 (lru_cache on the pure geometry functions) have landed and remove the user-visible cost: the ~30 redundant entity writes per update cycle and the repeated safety-margin math. This issue tracks the remaining CPU optimization that #540 was reaching for but did not land correctly: skipping _calculate_cover_state (coordinator.py) when no pipeline-relevant input has changed.

Why #540's version never fired

#540 gated the short-circuit on not self.state_change. In practice almost every _async_update_data runs with state_change=True, because the dominant triggers (sun.sun azimuth/elevation updates, chatty temperature/lux/irradiance sensors) all set that flag before the refresh. The fingerprint compare was never reached.

The correct design

Gate on a fingerprint regardless of state_change, with rounding so micro-updates that do not change the output are absorbed:

  • Round sun azimuth/elevation to ~1 dp and raw temps to whole degrees.
  • Include the derived climate threshold booleans (lux_below_threshold, irradiance_below_threshold, cloud_coverage_above_threshold, is_sunny, is_presence) so a threshold crossing always changes the fingerprint even when the rounded raw value looks stable.
  • Include every override/gate flag: manual, weather, motion, force, grace, in_time_window.
  • Include cover positions and custom-position sensor on/off states.
  • Always recompute on first_refresh, cover_state_change, auto_expired, and option changes (key off an options-version guard).

Use a structured tuple fingerprint rather than #540's MD5-of-JSON, so it stays debuggable and collision-free.

Why this is a separate, deliberate change

Any pipeline input left out of the fingerprint means covers silently stop moving. That is a correctness bug, not a perf regression, so it should not ride along with the low-risk write-gating change. Mitigations:

  • Keep an explicit whitelist of every input the pipeline reads.
  • Add a guard test that introspects the CoverStateSnapshot and ClimateReadings fields and fails if a new field is not represented in the fingerprint.

Layer 1 already removed the visible cost, so this is a pure coordinator-CPU win. Worth doing only once profiling on a busy instance (many entries, chatty sensors) shows pipeline CPU is material.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions