Skip to content

perf(serverless): defer CPU probe off worker import path - #629

Open
deanq wants to merge 1 commit into
mainfrom
deanq/sls-808-lazy-cpu-probe
Open

deanq wants to merge 1 commit into
mainfrom
deanq/sls-808-lazy-cpu-probe

Conversation

@deanq

@deanq deanq commented Oct 18, 2026 •

Copy link
Copy Markdown
Member

Summary

rp_debugger ran cpuinfo.get_cpu_info() at module level. rp_job imports rp_debugger unconditionally, so every serverless worker paid the CPU probe at startup, even though the value is only used when a job sets rp_debugger: true.

  • PROCESSOR constant replaced by a cached get_processor_info(), resolved on first debugger output
  • import cpuinfo moved inside it
  • Missing brand_raw still falls back to "Unable to get processor info."

The module-level PROCESSOR name is removed; nothing in the SDK referenced it outside the old test.

Impact

On x86 the probe is much more expensive than on macOS: py-cpuinfo measures clock speed in a child process around a fixed sleep(1) (CPUID.get_raw_hz). On arm64 it skips that path.

Measured on a real RTX 4090 serverless worker (AMD EPYC 7B13, 128 CPUs):

Time
cpuinfo.get_cpu_info() 1169 / 1171 / 1172 ms
Generated handler loaded -> first worker-start fitness check, 2.0.0rc1 1459 / 1469 ms
Same span with the lazy probe bundled 536 ms

"cpuinfo" in sys.modules was False inside the handler with the lazy probe. Locally, import runpod.serverless: ~240ms -> ~162ms (macOS arm64, warm, best of 3).

Test plan

  • New: subprocess test that cpuinfo is not in sys.modules after importing rp_job (fails on main)
  • New: probe runs once and is cached; fallback on missing brand_raw; debugger output includes processor
  • make quality-check: 1446 passed, 91.8% coverage

Linear: SLS-808, SLS-814

rp_debugger called cpuinfo.get_cpu_info() at module level, and rp_job
imports rp_debugger unconditionally, so every serverless worker paid a
~75ms CPU probe at startup. The result is only used when a job enables
rp_debugger.

- Replace the PROCESSOR constant with a cached get_processor_info(),
  resolved on first debugger output; import cpuinfo lazily inside it
- Add a cold-start test asserting cpuinfo is not loaded by rp_job
- import runpod.serverless: ~240ms -> ~162ms (macOS, warm)

SLS-808

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

馃煝 Approval recommended

The focused change preserves debugger output and fallback behavior, with targeted regression coverage and no unresolved findings.

No open issues 馃帀

What changed in this PR

Defers CPU detection until debugger output is requested, reducing serverless worker startup overhead.

Changes:

  • Replaces the eager CPU probe with a cached, lazy lookup.
  • Preserves the missing-processor fallback.
  • Adds regression tests for lazy loading, caching, and debugger output.
File Description
tests/鈥媡est_serverless/鈥媡est_utils/鈥媡est_debugger.py Tests processor caching, fallback, and output.
tests/鈥媡est_performance/鈥媡est_cold_start.py Checks worker imports do not load cpuinfo.
runpod/鈥媠erverless/鈥媢tils/鈥媟p_debugger.py Defers and caches CPU detection.

Review effort: Balanced

This branch has not been deployed

No deployments
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.

2 participants