Skip to content

[Feature] Reduce Slightly CPU Usage For Raspberry Pi 4#327

Open
antonio-amjr wants to merge 2 commits into
project-chip:v2.15.1-developfrom
antonio-amjr:feature/reduce_cpu_usage_for_rasp
Open

[Feature] Reduce Slightly CPU Usage For Raspberry Pi 4#327
antonio-amjr wants to merge 2 commits into
project-chip:v2.15.1-developfrom
antonio-amjr:feature/reduce_cpu_usage_for_rasp

Conversation

@antonio-amjr
Copy link
Copy Markdown
Contributor

@antonio-amjr antonio-amjr commented May 28, 2026

Fix: project-chip/certification-tool#911
In combination with: project-chip/certification-tool#1012

Descriptions

Reduce CPU usage on resource-constrained hardware (Raspberry Pi 4). Profiling on Raspberry Pi 4 identified several sources of unnecessary CPU load during idle operation and test execution. This PR addresses them.

Changes

  • WebSocket polling interval (web_sockets.py, socket_connection_manager.py): The previous value caused the event loop to wake up 10 times per second per connected client with no work to do.

  • Container startup polling (container_manager.py): Each poll hits the Docker daemon; 200ms was unnecessarily
    aggressive for a startup sequence with a 5s timeout.

  • Log processing interval (test_log_handler.py): The periodic task that flushes log entries to DB and broadcasts them over WebSocket was firing at 2 Hz during test execution with no user-visible benefit to the higher frequency.

  • TestUIObserver state isolation (test_ui_observer.py): Fixed __async_updates, __last_seen_run_state, and __last_seen_run_log_len being declared as class-level variables, causing state to leak across test runs. Moved to instance variables in __init__.

  • BaseManager IPC call reduction (python_testing_hooks_proxy.py, test_case.py): The hook polling loop was making two separate IPC calls per iteration (update_test() + is_finished()). A new get_update() method returns both values in a single call, halving the IPC rate. The poll interval was also corrected from0.0001s (effectively a busy-wait at 10,000 iterations/second) to 0.2s.

    Test plan

    • Run a full Python test suite and verify test execution completes correctly
    • Verify container startup still succeeds within timeout
    • Check log output is still written to file with expected content

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request adjusts several timeout and sleep intervals across the application, refactors the test runner update loop to use a single IPC call (get_update), moves TestUIObserver state variables to an init constructor, and removes backtrace logging. Feedback on these changes includes addressing potential latency in relay_video_frames caused by the increased websocket timeout, correcting indentation and type annotations in the new get_update method, and updating an outdated comment in container_manager.py to match the new sleep interval.

# WebSocketDisconnect is not raised unless we poll
# https://github.com/tiangolo/fastapi/issues/3008
await asyncio.wait_for(websocket.receive_text(), 0.1)
await asyncio.wait_for(websocket.receive_text(), 1.0)
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.

high

In relay_video_frames, when the UDP socket times out (after 1.0 second of no frames), the code polls the websocket with a 1.0-second timeout using asyncio.wait_for(websocket.receive_text(), 1.0). Since this is a receive-only video socket, the client will not send any text, causing this call to block for the full 1.0 second. During this blocking period, any incoming UDP video frames will be buffered or delayed, introducing up to 1.0 second of latency/stuttering when the video stream resumes.

To avoid this latency, consider running the UDP receiver and the websocket disconnect listener concurrently using asyncio.create_task and asyncio.wait(..., return_when=asyncio.FIRST_COMPLETED). This allows immediate detection of websocket disconnection without introducing any blocking delays in the UDP frame relay loop.

Comment thread app/container_manager/container_manager.py
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.

1 participant