Writing A Program That Uses Exactly 50% Cpu Utilization
Writing a program that uses exactly 50% CPU utilization
In one of my project, we needed to add noisy neighbor process. And apparently it was not very straightforward how it should be. The first program was simply alternating between doing work and sleeping for equal amounts of time.
- Busy wait for 1 millisecond - keeping the CPU at 100% utilization
- Sleep for 1 millisecond - letting the CPU rest at 0% utilization
It logically should achieve 50% CPU utilization. However, it does not.
Python code
import time
from datetime import datetime
i = 0
while True:
if i % 2 == 0:
sleep_in_ms = 1
sleep_in_second = sleep_in_ms * 0.001
time.sleep(sleep_in_second) # Sleep for 1ms
else:
start_time_ms = int(datetime.now().timestamp() * 1000)
while True:
current_time_ms = datetime.now().timestamp() * 1000
busy_wait_duration = current_time_ms - start_time_ms
if busy_wait_duration > sleep_in_ms: # Busy wait for 1ms
break
i += 1
The program alternates between sleeping and busy-waiting, each for exactly 1 millisecond. Too simple to think.
However, apparently if you run the program, you will see 37% not 50%.
Where did that missing 13% go?
I overlooked some factors that affects the CPU utilization other than my code itself. There are overall four different additional factors outside of your code logic that can affect the CPU utilization.
1. The Overhead Tax
Every operation in the program—checking the time, evaluating conditions, managing the loop—consumes CPU cycles. This overhead isn’t accounted for in my 1ms calculations. While individually tiny, these operations accumulate and eat into what should be “productive” busy-wait time.
2. Sleep Function Inaccuracy
The time.sleep()
function doesn’t provide microsecond precision. Operating systems typically have minimum sleep granularities, often much larger than 1 millisecond. When I requested a 1ms sleep, the actual sleep duration was frequently longer, skewing the balance toward more idle time.
3. Operating System Scheduling
Modern operating systems use complex scheduling algorithms. When my process wakes up from sleep, there’s no guarantee it will immediately resume execution. The scheduler might introduce additional delays, further reducing the actual busy-wait time.
4. System Interference
Other processes, system activities, and even hardware interrupts can influence how much CPU time my process actually receives, making precise control nearly impossible.
Solution
…