python.cpu_in_event_loop
Performance
Medium
Detects CPU-bound work (heavy computation, json.loads on large data, cryptographic operations) in async functions without run_in_executor().
Why It Matters
Section titled “Why It Matters”The async event loop runs on a single thread. CPU-intensive operations block that thread:
- All tasks stall — Every concurrent request waits
- Timeouts cascade — Other operations time out while waiting
- Async benefits lost — Your “async” code becomes sequential
Even a few hundred milliseconds of CPU work can destroy async performance under load.
Example
Section titled “Example”# ❌ Beforeasync def process_large_json(data): return json.loads(data) # Blocks event loopIf data is 10MB, this blocks the event loop for hundreds of milliseconds.
# ✅ Afterasync def process_large_json(data): loop = asyncio.get_event_loop() return await loop.run_in_executor(None, json.loads, data)run_in_executor offloads work to a thread pool, freeing the event loop.
What Unfault Detects
Section titled “What Unfault Detects”json.loads()/json.dumps()on potentially large data in async functions- Cryptographic operations (
hashlib,bcrypt, etc.) - Image processing (
PIL,cv2) - Data parsing (
pandas.read_csv, XML parsing) - Heavy computation loops
Auto-Fix
Section titled “Auto-Fix”Unfault wraps CPU-bound calls with run_in_executor.
Best Practices
Section titled “Best Practices”# For CPU-bound work in async codeloop = asyncio.get_event_loop()result = await loop.run_in_executor(None, cpu_bound_function, arg1, arg2)
# For many CPU-bound tasks, use a ProcessPoolExecutorfrom concurrent.futures import ProcessPoolExecutor
executor = ProcessPoolExecutor(max_workers=4)result = await loop.run_in_executor(executor, heavy_computation, data)