Skip to content

fix: offload map parsing to worker thread to prevent event loop blocking - #966

Open
allenporter wants to merge 1 commit into
Python-roborock:mainfrom
allenporter:fix-blocking-map-parsing
Open

allenporter wants to merge 1 commit into
Python-roborock:mainfrom
allenporter:fix-blocking-map-parsing

Conversation

@allenporter

Copy link
Copy Markdown
Contributor

Description

Offload CPU-intensive map parsing and rendering to worker threads via asyncio.to_thread to prevent blocking the asyncio event loop.

When devices are actively cleaning and returning map updates, parsing the raw map payload and rendering the map into PNG format runs synchronously on the asyncio event loop. In multi-device setups or frequent update cycles, this locks the event loop and leads to high latency spikes in downstream consumers like Home Assistant (see home-assistant/core#182656).

Changes

  • In MapContentTrait.refresh(): offload self.converter.convert(response) to a worker thread using await asyncio.to_thread(self.converter.convert, response).
  • In HomeTrait:
    • Factor cached map parsing into a helper function _parse_cached_home_map_content(...) and run it via await asyncio.to_thread(...) once, rather than running asyncio.to_thread per item in a loop.
    • Avoid redundant reparsing in _parse_cached_home_map_content when the cached bytes match the previously parsed raw_api_response.

Fixes home-assistant/core#182656

Copilot AI lite review requested due to automatic review settings September 20, 2026 19:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Concurrent refreshes can apply stale map data; serialization or generation checks are needed.

Review effort: Lite
Findings: None

What changed in this PR

This pull request offloads V1 map parsing and rendering to worker threads to reduce asyncio event-loop blocking.

Changes:

  • Runs map conversion via asyncio.to_thread.
  • Adds threaded cached-map parsing.
  • Reuses unchanged cached map content.
File Description
roborock/​devices/​traits/​v1/​map_content.py Offloads map conversion to a worker thread.
roborock/​devices/​traits/​v1/​home.py Offloads cached parsing and avoids redundant reparsing.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@allenporter
allenporter force-pushed the fix-blocking-map-parsing branch from b213233 to 10bbbda Compare September 20, 2026 19:17
Comment thread roborock/devices/traits/v1/map_content.py
@allenporter
allenporter force-pushed the fix-blocking-map-parsing branch from 10bbbda to b925c8d Compare September 20, 2026 19:22
@allenporter
allenporter marked this pull request as draft September 20, 2026 19:29
Comment thread roborock/devices/traits/v1/home.py Outdated
@allenporter
allenporter force-pushed the fix-blocking-map-parsing branch from b925c8d to 6f4275a Compare September 20, 2026 19:33
Offload CPU-intensive map parsing and rendering to worker threads via
`asyncio.to_thread` to prevent blocking the asyncio event loop.

- In `MapContentTrait.refresh()`, offload `self.converter.convert` to `asyncio.to_thread`.
- In `HomeTrait.discover_home()`, move cached map parsing to a helper function `_parse_cached_home_map_content` and run it via `asyncio.to_thread`.
- Avoid reparsing cached maps in `HomeTrait` when raw bytes are unchanged.

Addresses home-assistant/core#182656
@allenporter
allenporter force-pushed the fix-blocking-map-parsing branch from 6f4275a to 377d0ec Compare September 20, 2026 19:35
@allenporter
allenporter marked this pull request as ready for review September 20, 2026 20:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Roborock: map parsing blocks the event loop — GIL held 97% with multiple vacuums cleaning

2 participants