Story / scenario opener
Your Fedora laptop fan screams like a jet engine while you are just browsing the web. Or the desktop UI stutters every time you open a terminal, and the mouse cursor lags behind your hand. You suspect a rogue process is chewing up CPU cycles, but the system monitor shows nothing obvious. You need to find the resource hog fast, identify whether it is a legitimate workload or a bug, and stop it before the system locks up.
What's actually happening
The CPU divides time into slices and distributes them to processes. When a process grabs too many slices, other processes starve. High CPU usage falls into two categories. The first is legitimate work. Compiling code, transcoding video, or running dnf upgrade will max out the CPU. This is expected behavior. The system should be fast during these tasks, and the usage drops when the work finishes.
The second category is a problem. A process stuck in a loop, a memory leak causing thrashing, or a misconfigured service polling too aggressively will consume resources without producing value. Fedora's CFS scheduler tries to distribute time fairly, but a runaway thread can still drown the system. You need to distinguish between a heavy workload and a bug. The CPU doesn't care about your workflow. It executes instructions. Your job is to find which instructions are wasting cycles.
The fix or how-to
Start with htop. It provides an interactive, color-coded view that is easier to read than the default top. If htop is not installed, add it via dnf.
Here's how to install and launch htop for an interactive view of process resource usage.
sudo dnf install htop -y # Install htop from the default repositories for an interactive process viewer
htop # Launch the monitor to see real-time CPU and memory usage
Inside htop, press F6 to sort by CPU usage. The processes at the top are consuming the most cycles. Press H to toggle thread view. This reveals if a single process has spawned multiple threads that are all burning CPU. If you are on a minimal server without htop, use top and press Shift + P to sort by CPU.
For command-line reporting, pidstat gives you precise numbers. This tool is part of the sysstat package and updates at a fixed interval, making it easier to parse in scripts or logs.
Here's how to install sysstat and run pidstat for granular per-process CPU accounting.
sudo dnf install sysstat -y # Install sysstat to access pidstat and sar for detailed accounting
pidstat -u 1 # Report per-process CPU usage, updating every second
The output shows the PID, user, and CPU percentage for every active process. If you suspect a systemd service is the issue, check the cgroup hierarchy. Services often spawn multiple processes, and looking at PIDs alone can be confusing.
Here's how to check systemd-cgtop to see CPU usage grouped by systemd slices and services.
systemd-cgtop # Display CPU usage hierarchy by cgroup to identify service-level consumption
This displays usage by service name rather than PID. You can see if firefox.service or docker.service is the aggregate hog. For a quick snapshot without installing extra tools, use ps.
Here's how to run a ps command to get a quick list of the top CPU-consuming processes.
ps -eo pid,comm,%cpu --sort=-%cpu | head -n 10 # List the top 10 processes by CPU usage in descending order
journalctl -xe reads better than journalctl alone. The x flag adds explanatory text and the e flag jumps to the end. Most sysadmins type journalctl -xeu <unit> muscle-memory style. If a process is crashing and spiking CPU, check the logs for the specific unit.
Install the tools before the emergency. You won't remember the flags when the fan is screaming.
Verify it worked
How do you know the fix worked? The CPU usage drops, the fan slows down, and the system responds normally. Verify the load has stabilized by checking the load average and running a few iterations of pidstat.
Here's how to verify the CPU load has stabilized by checking the load average and current usage.
uptime # Show system load averages over 1, 5, and 15 minutes to check overall pressure
pidstat -u 1 3 # Run pidstat for three iterations to confirm the spike has subsided
Load average measures the number of processes waiting for CPU or I/O. If the 15-minute average is high, the system has been under pressure for a while. A single second of low usage doesn't mean the storm has passed. Watch the trend. If you enabled sysstat, you can also review historical data to see if the spike was a one-time event.
Here's how to enable historical data collection and review past CPU usage.
sudo systemctl enable --now sysstat # Enable and start the sysstat service for data collection
sar -u -f /var/log/sysstat/sa$(date +%d) # Review CPU usage history for today
sysstat collects data every 10 minutes by default. The sar command lets you replay that data. This is useful for diagnosing spikes that happened while you were away.
Trust the load average. A single second of low usage doesn't mean the storm has passed.
Common pitfalls and what the error looks like
You see a process with high CPU but you cannot kill it. Check the process state.
ps -p <PID> -o stat,cmd # Check the state of a specific process by PID
A state of D indicates uninterruptible sleep. The process is waiting for I/O, usually from a disk or network device. Sending SIGKILL will not work. The process is stuck in the kernel. If the hardware is unresponsive, a reboot may be the only option. A state of R means running. The process is actively executing instructions. You can kill an R state process.
Kernel threads like kworker or migration can also show high CPU. These are part of the kernel. High usage here often indicates hardware interrupts or driver issues. Check dmesg or journalctl -k for hardware errors. If you see Error: Transaction test error during an upgrade, the package manager is protecting you from a conflict. Read the error before forcing. A botched upgrade can leave you unable to boot.
Config files in /etc/ are user-modified. Files in /usr/lib/ ship with the package. Edit /etc/. Never edit /usr/lib/. If you need to change sysstat collection intervals, edit /etc/sysconfig/sysstat.
Check the process state before you panic. A D state process is waiting on hardware, not spinning in code.
When to use this vs alternatives
Use htop when you need an interactive, color-coded view to sort processes and kill them quickly. Use pidstat when you require precise numerical data for logging or scripting. Use systemd-cgtop when you suspect a systemd service or slice is consuming resources. Use top when you are on a minimal system without htop or sysstat installed. Use ps when you need a one-time snapshot for a script or quick check. Use journalctl -xe when a process is crashing or failing and you need the error log.
Pick the tool that matches the question. Interactive debugging needs htop. Auditing needs pidstat.