Configure Linux CPU and process scheduling with systemd and nice priorities for workload optimization

Intermediate 25 min Apr 03, 2026 2,166 views
Ubuntu 24.04 Ubuntu 22.04 Debian 12 AlmaLinux 9 Rocky Linux 9 Fedora 41

Learn to optimize Linux workloads by configuring CPU scheduling policies, setting process priorities with nice and ionice commands, and implementing systemd service limits for better resource allocation and performance.

Prerequisites

  • Root or sudo access
  • Basic understanding of Linux processes
  • Familiarity with systemd services

What this solves

Linux CPU scheduling determines which processes get processor time and in what order. By default, Linux uses the Completely Fair Scheduler (CFS) which gives equal CPU time to all processes, but production workloads often need fine-tuned resource allocation. This tutorial shows you how to prioritize critical services, limit resource-hungry applications, and optimize system performance through proper CPU scheduling configuration.

Understanding Linux process scheduling

Process priorities and nice values

Linux uses nice values ranging from -20 (highest priority) to +19 (lowest priority) to determine process scheduling priority. Lower nice values get more CPU time, while higher values get less. Regular users can only increase nice values (lower priority), while root can set any value.

The priority formula is: Priority = 20 + nice_value. A process with nice value -10 has priority 10, while nice value +10 gives priority 30. The kernel scheduler uses these priorities to allocate CPU time slices.

Scheduling policies

Linux supports multiple scheduling policies beyond the default CFS. Real-time policies like SCHED_FIFO and SCHED_RR provide deterministic scheduling for time-critical applications. SCHED_BATCH optimizes for throughput over latency, while SCHED_IDLE runs processes only when the system is otherwise idle.

PolicyUse casePriority range
SCHED_NORMAL (CFS)Default for most processesNice -20 to +19
SCHED_FIFOReal-time, first-in-first-outRT priority 1-99
SCHED_RRReal-time, round-robinRT priority 1-99
SCHED_BATCHCPU-intensive batch jobsNice -20 to +19
SCHED_IDLEBackground tasksNice +19 equivalent

Step-by-step configuration

Install scheduling tools

Install the utilities needed for process scheduling management and monitoring.

sudo apt update
sudo apt install -y util-linux schedutils htop iotop
sudo dnf install -y util-linux schedutils htop iotop

Check current process priorities

View current process priorities and scheduling information using standard Linux tools.

# View processes with priority information
ps -eo pid,ppid,ni,pri,psr,comm --sort=-ni | head -20

# Check scheduling policy for a specific process
chrt -p 1234

# View system load and process priorities
htop

Set process priorities with nice

Use nice to start processes with specific priority levels and renice to adjust running processes.

# Start a process with lower priority (higher nice value)
nice -n 10 find / -name "*.log" 2>/dev/null

# Start a CPU-intensive task with lowest priority
nice -n 19 tar czf backup.tar.gz /home/user/documents/

# As root, start a high-priority process
sudo nice -n -5 important-service

# Adjust priority of running process (find the PID first)
ps aux | grep find
sudo renice -10 -p 12345

Configure I/O scheduling with ionice

Set I/O scheduling classes and priorities to manage disk access priorities alongside CPU scheduling.

# Set I/O class to idle (only when system is idle)
ionice -c 3 -p 12345

# Set best-effort I/O with priority 7 (lowest)
ionice -c 2 -n 7 dd if=/dev/zero of=/tmp/testfile bs=1M count=1000

# Start process with real-time I/O priority (root only)
sudo ionice -c 1 -n 4 database-backup-script

# Check current I/O scheduling
ionice -p 12345
Note: I/O scheduling classes are: 0=none, 1=real-time, 2=best-effort, 3=idle. Real-time I/O can starve other processes and should be used carefully.

Set scheduling policies with chrt

Use chrt to configure advanced scheduling policies for real-time and batch processing requirements.

# Set SCHED_BATCH policy for CPU-intensive tasks
chrt -b 0 cpu-intensive-calculation

# Set SCHED_IDLE for background processes
chrt -i 0 background-maintenance-task

# Set real-time FIFO scheduling (root only)
sudo chrt -f 50 time-critical-application

# Set real-time round-robin scheduling
sudo chrt -r 30 -p 12345

# Check scheduling policy and priority
chrt -p 12345
Warning: Real-time scheduling policies can lock up your system if used incorrectly. Always test in non-production environments first and ensure processes have proper exit conditions.

Configure systemd service CPU limits

Create systemd service configurations with CPU scheduling and resource limits for consistent service management.

[Unit]
Description=High Priority Application
After=network.target

[Service]
Type=simple
User=appuser
Group=appgroup
ExecStart=/opt/myapp/bin/myapp
Restart=always

# CPU scheduling configuration
Nice=-10
CPUSchedulingPolicy=2
CPUSchedulingPriority=0
IOSchedulingClass=2
IOSchedulingPriority=2

# CPU resource limits
CPUQuota=200%
CPUWeight=200

[Install]
WantedBy=multi-user.target

Create batch processing service

Configure a systemd service optimized for batch processing with appropriate scheduling policies.

[Unit]
Description=Batch Processing Service
After=network.target

[Service]
Type=simple
User=batchuser
Group=batchgroup
ExecStart=/opt/batch/processor
Restart=on-failure

# Batch scheduling configuration
Nice=15
CPUSchedulingPolicy=3
IOSchedulingClass=3

# Resource constraints
CPUQuota=50%
CPUWeight=50
MemoryMax=2G

[Install]
WantedBy=multi-user.target

Configure CPU affinity and NUMA

Set CPU affinity to bind processes to specific CPU cores for improved performance and cache locality.

# Check system CPU topology
lscpu
numactl --hardware

# Bind process to specific CPUs (cores 0-3)
taskset -c 0-3 cpu-bound-application

# Bind process to CPU cores using hex mask (cores 0,2,4,6)
taskset 0x55 application

# Check current CPU affinity
taskset -p 12345

# Set CPU affinity for running process
sudo taskset -cp 0,2,4,6 12345

Configure systemd service with CPU affinity

Add CPU affinity settings to systemd service files for consistent CPU binding.

[Unit]
Description=CPU Bound Application
After=network.target

[Service]
Type=simple
User=appuser
ExecStart=/opt/app/cpu-intensive-app
Restart=always

# CPU affinity and scheduling
CPUAffinity=0-3
Nice=0
CPUSchedulingPolicy=0

# Resource limits
CPUQuota=400%
CPUWeight=100

[Install]
WantedBy=multi-user.target

Apply and verify systemd configurations

Reload systemd configuration and start services with the new scheduling settings.

# Reload systemd daemon
sudo systemctl daemon-reload

# Start and enable services
sudo systemctl enable --now high-priority.service
sudo systemctl enable --now batch-processor.service
sudo systemctl enable --now cpu-bound.service

# Check service status
sudo systemctl status high-priority.service
sudo systemctl status batch-processor.service

Configure CPU scheduling limits globally

Set system-wide limits and default scheduling parameters for better resource management.

# Set nice limits for users and groups
@developers     soft    nice    -10
@developers     hard    nice    -5
batchuser       soft    nice    15
batchuser       hard    nice    19

# Set real-time priority limits
@realtime       soft    rtprio  50
@realtime       hard    rtprio  80

# Memory limits
@developers     soft    memlock unlimited
@developers     hard    memlock unlimited

Configure kernel scheduler parameters

Tune kernel scheduler parameters for your workload requirements using sysctl.

# CFS scheduler tuning
kernel.sched_latency_ns = 6000000
kernel.sched_min_granularity_ns = 750000
kernel.sched_wakeup_granularity_ns = 1000000

# Real-time throttling (percentage of CPU time for RT tasks)
kernel.sched_rt_runtime_us = 950000
kernel.sched_rt_period_us = 1000000

# NUMA balancing
kernel.numa_balancing = 1

# Process scheduling
kernel.sched_autogroup_enabled = 0

Apply kernel parameters

Load the new kernel parameters and verify they are applied correctly.

# Apply sysctl settings
sudo sysctl -p /etc/sysctl.d/99-scheduler.conf

# Verify settings
sysctl kernel.sched_latency_ns
sysctl kernel.sched_rt_runtime_us
sysctl kernel.numa_balancing

# View all scheduler-related parameters
sysctl -a | grep sched

Monitor and troubleshoot CPU scheduling

Monitor CPU scheduling with top and htop

Use system monitoring tools to observe CPU scheduling behavior and process priorities in real-time.

# Monitor with enhanced top output
top -c -o %CPU
# Press 'f' to add fields, 'V' to show process hierarchy

# Use htop for better visualization
htop
# Press F6 to sort by CPU%, F4 to filter, F5 for tree view

# Monitor specific processes
watch -n 1 'ps -eo pid,ppid,ni,pri,psr,pcpu,comm --sort=-pcpu | head -15'

Use systemd tools for monitoring

Leverage systemd's built-in monitoring capabilities to track service resource usage and scheduling.

# Show service CPU usage
systemctl show high-priority.service --property=CPUUsageNSec
systemctl show batch-processor.service --property=CPUUsageNSec

# Monitor service resource usage
sudo systemd-cgtop

# View detailed service status
systemctl status high-priority.service
systemctl status batch-processor.service

# Check service resource limits
systemctl show high-priority.service | grep -E '(CPU|Memory|IO)'

Use performance monitoring tools

Deploy advanced monitoring tools to analyze CPU scheduling performance and identify bottlenecks.

# Monitor system performance with SAR
sar -u 1 10
sar -q 1 10

# Use iostat for I/O and CPU statistics
iostat -x 1 5

# Monitor process scheduling with pidstat
pidstat -u -p ALL 1 5
pidstat -w -p ALL 1 5

# Check CPU topology and usage
lscpu
mpstat -P ALL 1 5

Verify your setup

# Check service status and resource usage
sudo systemctl status high-priority.service batch-processor.service cpu-bound.service

# Verify process priorities and scheduling
ps -eo pid,ni,pri,psr,cls,comm --sort=-ni | head -20

# Check CPU affinity settings
taskset -p $(pgrep cpu-intensive-app)

# Monitor real-time CPU scheduling
htop

# Verify kernel scheduler parameters
sysctl kernel.sched_latency_ns kernel.sched_rt_runtime_us

# Check system load and CPU usage
uptime
sar -u 1 3

Common issues

SymptomCauseFix
High-priority process not getting CPU timeReal-time throttling limitsAdjust kernel.sched_rt_runtime_us or use SCHED_NORMAL with low nice value
System becomes unresponsiveReal-time process consuming all CPUUse sudo pkill -STOP process_name then adjust scheduling policy
Permission denied setting priorityUser lacks privilegesConfigure limits in /etc/security/limits.conf or run as root
Batch jobs interfering with interactive tasksIncorrect scheduling policyUse SCHED_BATCH or SCHED_IDLE for background processes
Poor performance on NUMA systemsProcess migrating between NUMA nodesSet CPU affinity with taskset or CPUAffinity in systemd
Systemd service limits not appliedService configuration errorCheck syntax with systemd-analyze verify service.service

Next steps

Automated install script

Run this to automate the entire setup

Wil je dit niet zelf beheren?

Wij beheren infrastructuur voor bedrijven die afhankelijk zijn van uptime. Volledig beheerd, met één vast aanspreekpunt dat je omgeving kent.

U krijgt één vast aanspreekpunt dat uw omgeving kent

Rotterdam 05:05 · bereikbaar in een bericht, geen ticketformulier