⚡ Optimizing Process Scheduling on Alpine Linux: Advanced Guide
Let’s optimize process scheduling on Alpine Linux for maximum performance! 🚀 This advanced tutorial shows you how to tune kernel scheduling parameters, configure CPU affinity, and optimize system performance for different workloads. Essential for high-performance servers and mission-critical applications! 😊
🤔 What is Process Scheduling Optimization?
Process scheduling optimization is the art of configuring how the kernel manages CPU time allocation and process execution! It’s crucial for system performance and responsiveness.
Process scheduling optimization is like:
- 🏁 A traffic controller managing busy intersections for optimal traffic flow
- ⚖️ A resource manager ensuring fair and efficient distribution of computing power
- 💡 A performance tuner that maximizes system throughput and minimizes latency
🎯 What You Need
Before we start, you need:
- ✅ Alpine Linux system with root access
- ✅ Understanding of Linux process management and kernel concepts
- ✅ Knowledge of system performance monitoring tools
- ✅ Backup plan in case kernel parameter changes cause issues
📋 Step 1: Understanding Linux Process Scheduling
Analyze Current Scheduling Configuration
Let’s examine your system’s current scheduling configuration! 😊
What we’re doing: Analyzing the current process scheduling parameters and system performance baseline.
# Check current kernel scheduler
cat /sys/kernel/debug/sched_features 2>/dev/null || \
echo "Scheduler debug info not available (normal for production kernels)"
# Check CPU information
cat /proc/cpuinfo | grep -E "(processor|model name|cpu MHz|cache size)" | head -20
# Check current scheduling policy and priority ranges
chrt -m
# Check system load and scheduling statistics
uptime
cat /proc/loadavg
cat /proc/stat | head -10
# Check current scheduler statistics
cat /proc/schedstat 2>/dev/null | head -5 || echo "schedstat not available"
# Check CPU governors
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 2>/dev/null | sort | uniq -c
What this shows: 📖 Your system’s current CPU configuration and scheduling behavior baseline.
Example output:
processor : 0
model name : Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
cpu MHz : 2200.000
cache size : 9216 KB
0.15 0.08 0.05 1/200 12345
SCHED_OTHER min/max priority : 0/0
SCHED_FIFO min/max priority : 1/99
SCHED_RR min/max priority : 1/99
SCHED_BATCH min/max priority : 0/0
SCHED_IDLE min/max priority : 0/0
SCHED_DEADLINE min/max priority : 0/0
What this means: You can see your CPU capabilities and scheduling policies available! ✅
Monitor Process Scheduling Behavior
Let’s monitor how processes are currently being scheduled! 🎯
What we’re doing: Using monitoring tools to observe scheduling behavior and identify optimization opportunities.
# Install monitoring tools
apk add htop iotop atop sysstat
# Monitor process scheduling in real-time
echo "Starting process monitoring (run each command in separate terminals):"
# Command 1: htop for interactive process monitoring
echo "htop - Interactive process viewer with scheduling info"
# Command 2: Monitor context switches and interrupts
cat > monitor_scheduling.sh << 'EOF'
#!/bin/sh
echo "=== Process Scheduling Monitor ==="
while true; do
echo "$(date): Context switches and load"
echo "Context switches: $(grep "^ctxt" /proc/stat | awk '{print $2}')"
echo "Processes running: $(grep "^procs_running" /proc/stat | awk '{print $2}')"
echo "Processes blocked: $(grep "^procs_blocked" /proc/stat | awk '{print $2}')"
echo "Load average: $(cut -d' ' -f1-3 /proc/loadavg)"
echo "Interrupts: $(grep "^intr" /proc/stat | awk '{print $2}')"
echo "------------------------"
sleep 5
done
EOF
chmod +x monitor_scheduling.sh
# Command 3: Check process priorities and scheduling policies
cat > process_analysis.sh << 'EOF'
#!/bin/sh
echo "=== Process Scheduling Analysis ==="
echo "Top CPU consumers with scheduling info:"
ps -eo pid,ppid,user,pri,ni,rtprio,sched,pcpu,pmem,time,comm --sort=-pcpu | head -15
echo -e "\nReal-time processes:"
ps -eo pid,ppid,user,pri,ni,rtprio,sched,pcpu,pmem,comm | grep -v "^[[:space:]]*[0-9]*[[:space:]]*[0-9]*[[:space:]]*[[:alpha:]]*[[:space:]]*[0-9]*[[:space:]]*0[[:space:]]*-" | head -10
echo -e "\nHigh priority processes (nice < 0):"
ps -eo pid,ppid,user,pri,ni,rtprio,sched,pcpu,pmem,comm | awk '$5 < 0' | head -10
EOF
chmod +x process_analysis.sh
echo "Monitoring scripts created! Run them to analyze scheduling behavior. 📊"
What this creates: Comprehensive monitoring tools for understanding scheduling behavior! ✅
💡 Important Tips
Tip: Always establish baseline performance before making any optimizations! 💡
Warning: Incorrect scheduling changes can severely impact system performance! ⚠️
🛠️ Step 2: Kernel Scheduling Parameter Tuning
Configure CFS (Completely Fair Scheduler) Parameters
Let’s optimize the default CFS scheduler parameters! 😊
What we’re doing: Tuning CFS scheduler parameters for better performance and responsiveness.
# Create sysctl configuration for scheduling optimization
cat > /etc/sysctl.d/99-scheduling-optimization.conf << 'EOF'
# CFS Scheduler Optimization
# Minimum preemption granularity (nanoseconds)
# Lower values = better interactivity, higher overhead
# Default: 1000000 (1ms), Optimized for desktop: 500000, server: 2000000
kernel.sched_min_granularity_ns = 1500000
# Wake-up granularity (nanoseconds)
# Controls when a waking task can preempt current task
# Lower = more responsive, higher CPU overhead
kernel.sched_wakeup_granularity_ns = 2000000
# Target preemption latency (nanoseconds)
# Time slice for runqueue with multiple tasks
# Lower = better interactivity, higher context switch overhead
kernel.sched_latency_ns = 12000000
# Migration cost (nanoseconds)
# Cost of migrating a task to another CPU
# Higher = less migration, better cache locality
kernel.sched_migration_cost_ns = 500000
# Number of tasks after which load balancing is triggered
# Higher = less frequent balancing, lower overhead
kernel.sched_nr_migrate = 32
# Autogroup feature for better desktop responsiveness
# 1 = enabled (good for mixed workloads), 0 = disabled (better for servers)
kernel.sched_autogroup_enabled = 0
# Real-time throttling (microseconds)
# Prevents RT tasks from starving the system
kernel.sched_rt_period_us = 1000000
kernel.sched_rt_runtime_us = 950000
# CPU utilization clamping
# Controls how aggressive the scheduler is about CPU utilization
kernel.sched_util_clamp_min = 0
kernel.sched_util_clamp_max = 1024
EOF
# Apply the configuration
sysctl -p /etc/sysctl.d/99-scheduling-optimization.conf
# Verify the changes
echo "=== Scheduler Configuration Applied ==="
sysctl kernel.sched_min_granularity_ns
sysctl kernel.sched_wakeup_granularity_ns
sysctl kernel.sched_latency_ns
sysctl kernel.sched_migration_cost_ns
echo "CFS scheduler optimized! ⚖️"
What these parameters do:
sched_min_granularity_ns
: Minimum time slice for CPU-bound taskssched_wakeup_granularity_ns
: Controls preemption of sleeping taskssched_latency_ns
: Target latency for multiple tasks on runqueuesched_migration_cost_ns
: Cost threshold for task migration between CPUs
What this means: Your scheduler is now tuned for optimal performance! 🎉
Configure CPU Frequency Scaling
Let’s optimize CPU frequency scaling for performance! 🚀
What we’re doing: Configuring CPU governors and frequency scaling for optimal performance characteristics.
# Install CPU frequency tools
apk add cpufrequtils
# Check available CPU governors
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
# Create CPU governor optimization script
cat > /usr/local/bin/optimize-cpu-governors.sh << 'EOF'
#!/bin/sh
CPU_COUNT=$(nproc)
WORKLOAD_TYPE=${1:-balanced}
case "$WORKLOAD_TYPE" in
"performance")
GOVERNOR="performance"
echo "Setting performance governor for maximum CPU performance"
;;
"powersave")
GOVERNOR="powersave"
echo "Setting powersave governor for minimum power consumption"
;;
"ondemand")
GOVERNOR="ondemand"
echo "Setting ondemand governor for dynamic scaling"
;;
"conservative")
GOVERNOR="conservative"
echo "Setting conservative governor for gradual scaling"
;;
"schedutil")
GOVERNOR="schedutil"
echo "Setting schedutil governor for scheduler-driven scaling"
;;
*)
GOVERNOR="ondemand"
echo "Setting balanced (ondemand) governor"
;;
esac
# Apply governor to all CPUs
for cpu in $(seq 0 $((CPU_COUNT-1))); do
if [ -f "/sys/devices/system/cpu/cpu$cpu/cpufreq/scaling_governor" ]; then
echo "$GOVERNOR" > "/sys/devices/system/cpu/cpu$cpu/cpufreq/scaling_governor"
echo "CPU $cpu: Governor set to $GOVERNOR"
fi
done
# Configure ondemand-specific parameters
if [ "$GOVERNOR" = "ondemand" ]; then
# Sampling rate (microseconds) - how often to check CPU usage
echo 20000 > /sys/devices/system/cpu/cpufreq/ondemand/sampling_rate
# Up threshold - CPU usage % to scale up
echo 80 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold
# Sampling down factor - how many samples before considering scale down
echo 5 > /sys/devices/system/cpu/cpufreq/ondemand/sampling_down_factor
echo "Ondemand parameters optimized"
fi
# Configure conservative-specific parameters
if [ "$GOVERNOR" = "conservative" ]; then
echo 20000 > /sys/devices/system/cpu/cpufreq/conservative/sampling_rate
echo 80 > /sys/devices/system/cpu/cpufreq/conservative/up_threshold
echo 20 > /sys/devices/system/cpu/cpufreq/conservative/down_threshold
echo 1 > /sys/devices/system/cpu/cpufreq/conservative/freq_step
echo "Conservative parameters optimized"
fi
echo "CPU governor optimization completed for workload type: $WORKLOAD_TYPE"
EOF
chmod +x /usr/local/bin/optimize-cpu-governors.sh
# Apply optimal governor for server workloads
/usr/local/bin/optimize-cpu-governors.sh performance
# Check current CPU frequencies
cat > /usr/local/bin/check-cpu-freq.sh << 'EOF'
#!/bin/sh
echo "=== CPU Frequency Status ==="
for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq; do
if [ -f "$cpu" ]; then
cpu_num=$(echo "$cpu" | grep -o 'cpu[0-9]*' | grep -o '[0-9]*')
freq=$(cat "$cpu")
governor=$(cat "/sys/devices/system/cpu/cpu$cpu_num/cpufreq/scaling_governor")
echo "CPU $cpu_num: ${freq} kHz (governor: $governor)"
fi
done
EOF
chmod +x /usr/local/bin/check-cpu-freq.sh
/usr/local/bin/check-cpu-freq.sh
echo "CPU frequency scaling optimized! ⚡"
What this does: Configures CPU governors for optimal performance based on workload type! ✅
Configure Process Priorities and Nice Values
Let’s set up intelligent process priority management! 🎮
What we’re doing: Creating scripts to automatically adjust process priorities based on system workload.
# Create dynamic priority adjustment script
cat > /usr/local/bin/dynamic-priority-manager.sh << 'EOF'
#!/bin/sh
# Configuration
HIGH_PRIORITY_PROCESSES="nginx apache2 mysql postgres redis"
LOW_PRIORITY_PROCESSES="backup rsync compile make gcc"
SYSTEM_LOAD_THRESHOLD=0.8
get_system_load() {
awk '{print $1}' /proc/loadavg
}
get_cpu_count() {
nproc
}
adjust_process_priority() {
local process_name=$1
local nice_value=$2
local action=$3
pids=$(pgrep "$process_name" 2>/dev/null)
if [ -n "$pids" ]; then
for pid in $pids; do
current_nice=$(ps -o ni= -p "$pid" 2>/dev/null | tr -d ' ')
if [ -n "$current_nice" ]; then
renice "$nice_value" -p "$pid" >/dev/null 2>&1
echo "$action: $process_name (PID: $pid) nice: $current_nice -> $nice_value"
fi
done
fi
}
# Main priority adjustment logic
system_load=$(get_system_load)
cpu_count=$(get_cpu_count)
load_per_cpu=$(echo "$system_load $cpu_count" | awk '{printf "%.2f", $1/$2}')
echo "=== Dynamic Priority Manager ==="
echo "System load: $system_load (load per CPU: $load_per_cpu)"
echo "CPU count: $cpu_count"
# High system load - prioritize critical services
if [ "$(echo "$load_per_cpu > $SYSTEM_LOAD_THRESHOLD" | bc -l 2>/dev/null || echo "0")" = "1" ]; then
echo "High system load detected - adjusting priorities"
# Boost critical services
for process in $HIGH_PRIORITY_PROCESSES; do
adjust_process_priority "$process" "-5" "BOOST"
done
# Lower priority for non-critical processes
for process in $LOW_PRIORITY_PROCESSES; do
adjust_process_priority "$process" "10" "LOWER"
done
else
echo "Normal system load - maintaining standard priorities"
# Reset to normal priorities
for process in $HIGH_PRIORITY_PROCESSES; do
adjust_process_priority "$process" "0" "RESET"
done
for process in $LOW_PRIORITY_PROCESSES; do
adjust_process_priority "$process" "5" "NORMAL"
done
fi
# Special handling for real-time processes
echo -e "\nReal-time process management:"
# Check for processes that should run with real-time priority
RT_PROCESSES="irq migration rcu_"
for rt_process in $RT_PROCESSES; do
pids=$(pgrep "$rt_process" 2>/dev/null)
if [ -n "$pids" ]; then
for pid in $pids; do
current_policy=$(chrt -p "$pid" 2>/dev/null | awk '{print $2}')
if [ "$current_policy" != "SCHED_FIFO" ] && [ "$current_policy" != "SCHED_RR" ]; then
echo "RT: $rt_process (PID: $pid) keeping real-time scheduling"
fi
done
fi
done
echo "Priority adjustment completed at $(date)"
EOF
chmod +x /usr/local/bin/dynamic-priority-manager.sh
# Install bc for floating point calculations
apk add bc
# Test the priority manager
/usr/local/bin/dynamic-priority-manager.sh
echo "Dynamic priority management configured! 🎛️"
What this does: Automatically adjusts process priorities based on system load and process importance! 🌟
🔧 Step 3: CPU Affinity and NUMA Optimization
Configure CPU Affinity
Let’s optimize CPU affinity for better performance! 😊
What we’re doing: Setting up CPU affinity to bind processes to specific CPU cores for better cache locality.
# Check NUMA topology
numactl --hardware 2>/dev/null || echo "NUMA tools not available (single-node system)"
# Install CPU affinity tools
apk add util-linux
# Create CPU affinity optimization script
cat > /usr/local/bin/cpu-affinity-optimizer.sh << 'EOF'
#!/bin/sh
CPU_COUNT=$(nproc)
HALF_CPU=$((CPU_COUNT / 2))
echo "=== CPU Affinity Optimizer ==="
echo "Total CPUs: $CPU_COUNT"
# Function to set CPU affinity for a process
set_cpu_affinity() {
local process_name=$1
local cpu_mask=$2
local description=$3
pids=$(pgrep "$process_name" 2>/dev/null)
if [ -n "$pids" ]; then
for pid in $pids; do
taskset -p "$cpu_mask" "$pid" >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo "✅ $description: $process_name (PID: $pid) -> CPUs: $cpu_mask"
else
echo "❌ Failed to set affinity for $process_name (PID: $pid)"
fi
done
fi
}
# Strategy 1: Isolate web servers to specific cores
if [ "$CPU_COUNT" -ge 4 ]; then
echo -e "\nWeb server isolation (first half of CPUs):"
WEB_CPU_MASK="0-$((HALF_CPU-1))"
set_cpu_affinity "nginx" "$WEB_CPU_MASK" "Web server"
set_cpu_affinity "apache2" "$WEB_CPU_MASK" "Web server"
set_cpu_affinity "httpd" "$WEB_CPU_MASK" "Web server"
echo -e "\nDatabase isolation (second half of CPUs):"
DB_CPU_MASK="$HALF_CPU-$((CPU_COUNT-1))"
set_cpu_affinity "mysql" "$DB_CPU_MASK" "Database"
set_cpu_affinity "postgres" "$DB_CPU_MASK" "Database"
set_cpu_affinity "redis" "$DB_CPU_MASK" "Cache"
else
echo "System has fewer than 4 CPUs - using balanced approach"
fi
# Strategy 2: Isolate interrupt handling
echo -e "\nInterrupt handling optimization:"
# Move network interrupts to specific CPUs
if [ -d "/proc/irq" ]; then
for irq in /proc/irq/*/smp_affinity; do
if [ -f "$irq" ]; then
irq_num=$(echo "$irq" | grep -o '[0-9]*')
irq_name=$(cat "/proc/irq/$irq_num/name" 2>/dev/null || echo "unknown")
# Network interrupts to first CPU
if echo "$irq_name" | grep -qi "eth\|network\|nic"; then
echo "1" > "$irq" 2>/dev/null
echo "Network IRQ $irq_num ($irq_name) -> CPU 0"
fi
fi
done
fi
# Strategy 3: CPU-intensive processes isolation
echo -e "\nCPU-intensive process management:"
CPU_INTENSIVE="compile make gcc g++ ld"
if [ "$CPU_COUNT" -gt 2 ]; then
# Use last CPU for CPU-intensive tasks
INTENSIVE_CPU_MASK="$((CPU_COUNT-1))"
for process in $CPU_INTENSIVE; do
set_cpu_affinity "$process" "$INTENSIVE_CPU_MASK" "CPU-intensive"
done
fi
# Strategy 4: Real-time process affinity
echo -e "\nReal-time process affinity:"
RT_PROCESSES="migration rcu_ ksoftirqd"
if [ "$CPU_COUNT" -gt 1 ]; then
# Dedicate first CPU to real-time processes
for rt_process in $RT_PROCESSES; do
set_cpu_affinity "$rt_process" "0" "Real-time"
done
fi
# Show current CPU affinity status
echo -e "\n=== Current CPU Affinity Status ==="
echo "PID COMMAND CPU_AFFINITY"
ps -eo pid,comm | while read pid comm; do
if [ "$pid" != "PID" ] && [ -n "$pid" ]; then
affinity=$(taskset -p "$pid" 2>/dev/null | grep -o '[0-9a-f,]*$' || echo "error")
if [ "$affinity" != "error" ] && [ ${#comm} -lt 15 ]; then
printf "%-6s %-15s %s\n" "$pid" "$comm" "$affinity"
fi
fi
done | head -20
echo "CPU affinity optimization completed!"
EOF
chmod +x /usr/local/bin/cpu-affinity-optimizer.sh
# Run CPU affinity optimization
/usr/local/bin/cpu-affinity-optimizer.sh
echo "CPU affinity optimization configured! 🧭"
What this does: Optimally distributes processes across CPU cores for better performance! ✅
Configure NUMA-Aware Scheduling
Let’s optimize for NUMA (Non-Uniform Memory Access) systems! 🚀
What we’re doing: Configuring NUMA-aware process scheduling and memory allocation.
# Install NUMA control tools
apk add numactl
# Create NUMA optimization script
cat > /usr/local/bin/numa-optimizer.sh << 'EOF'
#!/bin/sh
echo "=== NUMA Topology Analysis ==="
# Check if NUMA is available
if ! command -v numactl >/dev/null 2>&1; then
echo "NUMA tools not available - installing..."
apk add numactl
fi
# Display NUMA topology
echo "NUMA hardware information:"
numactl --hardware 2>/dev/null || {
echo "No NUMA hardware detected - system is likely UMA (Uniform Memory Access)"
echo "NUMA optimizations not needed for this system"
exit 0
}
NUMA_NODES=$(numactl --hardware | grep "available:" | awk '{print $2}')
echo "NUMA nodes available: $NUMA_NODES"
if [ "$NUMA_NODES" -le 1 ]; then
echo "Single NUMA node detected - limited NUMA optimizations available"
exit 0
fi
echo -e "\nNUMA distance matrix:"
numactl --hardware | grep "node distances" -A 10
# Function to run process with NUMA binding
run_with_numa_binding() {
local process_name=$1
local numa_node=$2
local memory_policy=$3
pids=$(pgrep "$process_name" 2>/dev/null)
if [ -n "$pids" ]; then
for pid in $pids; do
# Set CPU affinity to NUMA node
numactl --cpunodebind="$numa_node" --membind="$numa_node" --pid="$pid" 2>/dev/null
if [ $? -eq 0 ]; then
echo "✅ NUMA binding: $process_name (PID: $pid) -> Node: $numa_node"
else
echo "❌ Failed to set NUMA binding for $process_name (PID: $pid)"
fi
done
fi
}
# NUMA optimization strategies
echo -e "\n=== NUMA Optimization Strategies ==="
# Strategy 1: Database processes on dedicated NUMA nodes
echo "Database NUMA optimization:"
if [ "$NUMA_NODES" -ge 2 ]; then
run_with_numa_binding "mysql" "0" "bind"
run_with_numa_binding "postgres" "0" "bind"
run_with_numa_binding "mongodb" "0" "bind"
fi
# Strategy 2: Web servers on separate NUMA nodes
echo "Web server NUMA optimization:"
if [ "$NUMA_NODES" -ge 2 ]; then
run_with_numa_binding "nginx" "1" "bind"
run_with_numa_binding "apache2" "1" "bind"
fi
# Strategy 3: Memory-intensive applications
echo "Memory-intensive application optimization:"
MEMORY_INTENSIVE="redis memcached elasticsearch"
NODE=0
for process in $MEMORY_INTENSIVE; do
if [ "$NODE" -lt "$NUMA_NODES" ]; then
run_with_numa_binding "$process" "$NODE" "bind"
NODE=$((NODE + 1))
if [ "$NODE" -ge "$NUMA_NODES" ]; then
NODE=0
fi
fi
done
# Configure kernel NUMA balancing
echo -e "\n=== Kernel NUMA Balancing ==="
NUMA_BALANCING="/proc/sys/kernel/numa_balancing"
if [ -f "$NUMA_BALANCING" ]; then
current_balancing=$(cat "$NUMA_BALANCING")
echo "Current NUMA balancing: $current_balancing"
# Enable NUMA balancing for better automatic migration
echo 1 > "$NUMA_BALANCING"
echo "NUMA balancing enabled"
else
echo "NUMA balancing not available in this kernel"
fi
# Show NUMA memory usage
echo -e "\n=== NUMA Memory Usage ==="
numastat 2>/dev/null || echo "numastat not available"
# Create NUMA monitoring script
cat > /usr/local/bin/numa-monitor.sh << 'NUMA_EOF'
#!/bin/sh
echo "=== NUMA Performance Monitor ==="
echo "Date: $(date)"
echo -e "\nNUMA memory statistics:"
numastat -m 2>/dev/null | head -20
echo -e "\nPer-process NUMA mapping:"
for pid in $(ps -eo pid --no-headers | head -10); do
if [ -f "/proc/$pid/numa_maps" ]; then
cmd=$(ps -p "$pid" -o comm --no-headers 2>/dev/null)
echo "PID $pid ($cmd):"
cat "/proc/$pid/numa_maps" 2>/dev/null | head -3
echo
fi
done
echo -e "\nNUMA hit/miss statistics:"
cat /proc/vmstat | grep numa
NUMA_EOF
chmod +x /usr/local/bin/numa-monitor.sh
echo "NUMA optimization completed!"
echo "Run /usr/local/bin/numa-monitor.sh to monitor NUMA performance"
EOF
chmod +x /usr/local/bin/numa-optimizer.sh
# Run NUMA optimization
/usr/local/bin/numa-optimizer.sh
echo "NUMA optimization configured! 🗺️"
What this does: Optimizes memory access patterns and process placement for NUMA systems! 🌟
📊 Quick Process Scheduling Commands Table
Command | Purpose | Result |
---|---|---|
🔧 chrt -p PID | Check process scheduling policy | ✅ View scheduling info |
🔍 taskset -p PID | Check CPU affinity | ✅ View CPU binding |
🚀 renice -5 PID | Increase process priority | ✅ Higher CPU priority |
📋 numactl --hardware | Show NUMA topology | ✅ NUMA configuration |
🎮 Practice Time!
Let’s practice what you learned! Try these optimization scenarios:
Example 1: High-Performance Web Server Optimization 🟢
What we’re doing: Optimizing process scheduling for a high-traffic web server scenario.
# Create web server optimization profile
cat > /usr/local/bin/webserver-optimization.sh << 'EOF'
#!/bin/sh
echo "🌐 Web Server Performance Optimization"
echo "======================================"
CPU_COUNT=$(nproc)
TOTAL_MEMORY=$(free -m | awk '/^Mem:/ {print $2}')
echo "System specs: $CPU_COUNT CPUs, ${TOTAL_MEMORY}MB RAM"
# Optimize for web server workload
echo "Applying web server optimizations..."
# 1. Scheduler tuning for responsiveness
sysctl -w kernel.sched_min_granularity_ns=750000
sysctl -w kernel.sched_wakeup_granularity_ns=1000000
sysctl -w kernel.sched_latency_ns=8000000
# 2. Network interrupt optimization
echo "Optimizing network interrupts..."
for irq in /proc/irq/*/smp_affinity; do
if [ -f "$irq" ]; then
irq_num=$(echo "$irq" | grep -o '[0-9]*')
# Distribute network IRQs across first half of CPUs
if [ "$CPU_COUNT" -gt 2 ]; then
mask="3" # CPUs 0 and 1
else
mask="1" # CPU 0 only
fi
echo "$mask" > "$irq" 2>/dev/null
fi
done
# 3. Web server process optimization
WEB_PROCESSES="nginx apache2 httpd"
for process in $WEB_PROCESSES; do
pids=$(pgrep "$process" 2>/dev/null)
if [ -n "$pids" ]; then
for pid in $pids; do
# High priority for web server
renice -5 "$pid" >/dev/null 2>&1
# Bind to specific CPUs if enough available
if [ "$CPU_COUNT" -gt 4 ]; then
taskset -p "0-$((CPU_COUNT/2-1))" "$pid" >/dev/null 2>&1
fi
echo "✅ Optimized $process (PID: $pid)"
done
fi
done
# 4. Background process deprioritization
BACKGROUND_PROCESSES="rsync backup tar gzip"
for process in $BACKGROUND_PROCESSES; do
pids=$(pgrep "$process" 2>/dev/null)
if [ -n "$pids" ]; then
for pid in $pids; do
renice 10 "$pid" >/dev/null 2>&1
echo "⬇️ Deprioritized $process (PID: $pid)"
done
fi
done
# 5. Memory optimization
echo "Configuring memory management..."
sysctl -w vm.swappiness=10
sysctl -w vm.dirty_ratio=15
sysctl -w vm.dirty_background_ratio=5
# 6. TCP optimization for web traffic
echo "Optimizing network stack..."
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_max_syn_backlog=65535
sysctl -w net.core.netdev_max_backlog=5000
echo "🎯 Web server optimization completed!"
echo "Monitor with: htop, iotop, /usr/local/bin/process_analysis.sh"
EOF
chmod +x /usr/local/bin/webserver-optimization.sh
# Run web server optimization
/usr/local/bin/webserver-optimization.sh
echo "Web server optimization example completed! 🌟"
What this does: Shows comprehensive optimization for web server workloads! 🌟
Example 2: Database Server Performance Tuning 🟡
What we’re doing: Optimizing process scheduling for database-intensive workloads.
# Create database optimization profile
cat > /usr/local/bin/database-optimization.sh << 'EOF'
#!/bin/sh
echo "🗃️ Database Server Performance Optimization"
echo "==========================================="
CPU_COUNT=$(nproc)
MEMORY_MB=$(free -m | awk '/^Mem:/ {print $2}')
echo "System: $CPU_COUNT CPUs, ${MEMORY_MB}MB RAM"
# Database-specific optimizations
echo "Applying database optimizations..."
# 1. Scheduler tuning for I/O workloads
sysctl -w kernel.sched_min_granularity_ns=2000000
sysctl -w kernel.sched_wakeup_granularity_ns=3000000
sysctl -w kernel.sched_latency_ns=20000000
# 2. I/O scheduler optimization
for device in /sys/block/*/queue/scheduler; do
if [ -f "$device" ]; then
device_name=$(echo "$device" | cut -d'/' -f4)
# Use deadline scheduler for database workloads
echo "deadline" > "$device" 2>/dev/null || echo "mq-deadline" > "$device" 2>/dev/null
echo "📀 $device_name: I/O scheduler set to deadline"
fi
done
# 3. Database process prioritization
DB_PROCESSES="mysql postgres mongodb redis memcached"
for process in $DB_PROCESSES; do
pids=$(pgrep "$process" 2>/dev/null)
if [ -n "$pids" ]; then
for pid in $pids; do
# High priority for database processes
renice -10 "$pid" >/dev/null 2>&1
# Bind to dedicated CPU cores
if [ "$CPU_COUNT" -gt 4 ]; then
# Use second half of CPUs for databases
start_cpu=$((CPU_COUNT / 2))
end_cpu=$((CPU_COUNT - 1))
taskset -p "$start_cpu-$end_cpu" "$pid" >/dev/null 2>&1
fi
echo "✅ Optimized $process (PID: $pid)"
done
fi
done
# 4. Memory and swap optimization
echo "Configuring memory for database workloads..."
sysctl -w vm.swappiness=1
sysctl -w vm.dirty_ratio=5
sysctl -w vm.dirty_background_ratio=2
sysctl -w vm.dirty_expire_centisecs=1000
sysctl -w vm.dirty_writeback_centisecs=200
# 5. Filesystem optimization
echo "Optimizing filesystem parameters..."
sysctl -w fs.file-max=2097152
# 6. Large memory page support
if [ -d "/sys/kernel/mm/transparent_hugepage" ]; then
echo "always" > /sys/kernel/mm/transparent_hugepage/enabled
echo "💾 Transparent huge pages enabled"
fi
# 7. Database connection limits
echo "Configuring connection limits..."
sysctl -w fs.nr_open=1048576
# 8. Background process management
NON_DB_PROCESSES="crond logrotate updatedb"
for process in $NON_DB_PROCESSES; do
pids=$(pgrep "$process" 2>/dev/null)
if [ -n "$pids" ]; then
for pid in $pids; do
renice 15 "$pid" >/dev/null 2>&1
# Bind to last CPU
if [ "$CPU_COUNT" -gt 2 ]; then
taskset -p "$((CPU_COUNT - 1))" "$pid" >/dev/null 2>&1
fi
echo "⬇️ Background process $process optimized"
done
fi
done
# Create database monitoring script
cat > /usr/local/bin/database-monitor.sh << 'DB_EOF'
#!/bin/sh
echo "=== Database Performance Monitor ==="
echo "$(date)"
echo -e "\nDatabase process status:"
ps -eo pid,ppid,user,pri,ni,pcpu,pmem,time,comm | grep -E "(mysql|postgres|mongo|redis)" | head -10
echo -e "\nI/O statistics:"
iostat -x 1 1 2>/dev/null | tail -n +4 || echo "iostat not available"
echo -e "\nMemory usage:"
free -h
echo -e "\nSwap usage:"
cat /proc/meminfo | grep -E "(SwapTotal|SwapFree|SwapCached)"
echo -e "\nTop I/O processes:"
iotop -a -o -d 1 -n 1 2>/dev/null | head -10 || echo "iotop not available"
DB_EOF
chmod +x /usr/local/bin/database-monitor.sh
echo "🎯 Database optimization completed!"
echo "Monitor with: /usr/local/bin/database-monitor.sh"
EOF
chmod +x /usr/local/bin/database-optimization.sh
# Run database optimization
/usr/local/bin/database-optimization.sh
echo "Database optimization example completed! 📚"
What this does: Demonstrates specialized optimization for database server workloads! 📚
🚨 Fix Common Problems
Problem 1: System becomes unresponsive after scheduling changes ❌
What happened: Aggressive scheduling changes caused system instability. How to fix it: Reset to default values and apply changes gradually.
# Emergency reset script
cat > /usr/local/bin/emergency-reset-scheduling.sh << 'EOF'
#!/bin/sh
echo "🚨 Emergency Scheduling Reset"
echo "============================"
# Reset to conservative default values
sysctl -w kernel.sched_min_granularity_ns=1000000
sysctl -w kernel.sched_wakeup_granularity_ns=1500000
sysctl -w kernel.sched_latency_ns=6000000
sysctl -w kernel.sched_migration_cost_ns=500000
# Reset CPU governors to ondemand
for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
if [ -f "$cpu" ]; then
echo "ondemand" > "$cpu" 2>/dev/null
fi
done
# Reset process priorities
echo "Resetting process priorities..."
ps -eo pid | while read pid; do
if [ "$pid" != "PID" ] && [ -n "$pid" ]; then
renice 0 "$pid" >/dev/null 2>&1
fi
done
echo "✅ Emergency reset completed"
EOF
chmod +x /usr/local/bin/emergency-reset-scheduling.sh
Problem 2: High context switching overhead ❌
What happened: Too many context switches degrading performance. How to fix it: Increase scheduler granularity and reduce migration.
# Reduce context switching
sysctl -w kernel.sched_min_granularity_ns=3000000
sysctl -w kernel.sched_latency_ns=24000000
sysctl -w kernel.sched_migration_cost_ns=1000000
# Monitor context switches
watch -n 1 'grep "^ctxt" /proc/stat'
Don’t worry! Scheduling optimization is an iterative process that requires careful tuning! 💪
💡 Simple Tips
- Start with baseline measurements 📅 - Always measure before and after changes
- Apply changes incrementally 🌱 - Make one change at a time and test
- Monitor system behavior 🤝 - Use monitoring tools to observe impact
- Have a rollback plan 💪 - Keep emergency reset procedures ready
✅ Check Everything Works
Let’s verify your process scheduling optimization is working perfectly:
# Complete process scheduling verification
cat > /usr/local/bin/scheduling-verification.sh << 'EOF'
#!/bin/sh
echo "=== Process Scheduling Optimization Verification ==="
echo "1. Current scheduler parameters:"
echo "Min granularity: $(sysctl -n kernel.sched_min_granularity_ns) ns"
echo "Wake granularity: $(sysctl -n kernel.sched_wakeup_granularity_ns) ns"
echo "Latency: $(sysctl -n kernel.sched_latency_ns) ns"
echo "Migration cost: $(sysctl -n kernel.sched_migration_cost_ns) ns"
echo -e "\n2. CPU governor status:"
for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
if [ -f "$cpu" ]; then
cpu_num=$(echo "$cpu" | grep -o 'cpu[0-9]*' | grep -o '[0-9]*')
governor=$(cat "$cpu")
echo "CPU $cpu_num: $governor"
fi
done | head -4
echo -e "\n3. System load and scheduling stats:"
echo "Load average: $(cut -d' ' -f1-3 /proc/loadavg)"
echo "Context switches: $(grep "^ctxt" /proc/stat | awk '{print $2}')"
echo "Running processes: $(grep "^procs_running" /proc/stat | awk '{print $2}')"
echo "Blocked processes: $(grep "^procs_blocked" /proc/stat | awk '{print $2}')"
echo -e "\n4. High priority processes:"
ps -eo pid,pri,ni,pcpu,comm --sort=-pcpu | head -8
echo -e "\n5. CPU affinity examples:"
ps -eo pid,comm | head -10 | while read pid comm; do
if [ "$pid" != "PID" ] && [ -n "$pid" ]; then
affinity=$(taskset -p "$pid" 2>/dev/null | grep -o '[0-9a-f,]*$' || echo "N/A")
printf "PID %-6s %-15s Affinity: %s\n" "$pid" "$comm" "$affinity"
fi
done | head -5
echo -e "\n6. Performance benchmark (simple CPU test):"
time_start=$(date +%s.%N)
dd if=/dev/zero of=/dev/null bs=1M count=1000 2>/dev/null
time_end=$(date +%s.%N)
duration=$(echo "$time_end - $time_start" | bc -l)
echo "CPU benchmark completed in ${duration} seconds"
echo -e "\n7. Memory performance:"
echo "Available memory: $(free -h | awk '/^Mem:/ {print $7}')"
echo "Swap usage: $(free -h | awk '/^Swap:/ {print $3 "/" $2}')"
echo -e "\n8. I/O scheduler status:"
for device in /sys/block/*/queue/scheduler; do
if [ -f "$device" ]; then
device_name=$(echo "$device" | cut -d'/' -f4)
scheduler=$(cat "$device" | grep -o '\[.*\]' | tr -d '[]')
echo "$device_name: $scheduler"
fi
done | head -3
echo -e "\n✅ Process scheduling optimization verification completed!"
echo "📊 Use htop, iotop, and custom monitoring scripts for ongoing analysis"
EOF
chmod +x /usr/local/bin/scheduling-verification.sh
/usr/local/bin/scheduling-verification.sh
echo "Process scheduling optimization verified! ✅"
Good output shows:
=== Process Scheduling Optimization Verification ===
1. Current scheduler parameters:
Min granularity: 1500000 ns
Wake granularity: 2000000 ns
Latency: 12000000 ns
Migration cost: 500000 ns
2. CPU governor status:
CPU 0: performance
CPU 1: performance
3. System load and scheduling stats:
Load average: 0.15 0.08 0.05
Context switches: 1234567
Running processes: 1
Blocked processes: 0
✅ Process scheduling optimization verification completed!
🏆 What You Learned
Great job! Now you can:
- ✅ Analyze and monitor process scheduling behavior on Alpine Linux
- ✅ Optimize CFS (Completely Fair Scheduler) parameters for different workloads
- ✅ Configure CPU frequency scaling and governor policies
- ✅ Implement dynamic process priority management systems
- ✅ Set up CPU affinity optimization for better cache locality
- ✅ Configure NUMA-aware scheduling and memory allocation
- ✅ Create workload-specific optimization profiles (web server, database)
- ✅ Monitor and troubleshoot scheduling performance issues
- ✅ Implement emergency recovery procedures for scheduling problems
🎯 What’s Next?
Now you can try:
- 📚 Exploring real-time scheduling with SCHED_FIFO and SCHED_RR policies
- 🛠️ Setting up advanced cgroup-based resource management and isolation
- 🤝 Implementing container-aware scheduling optimization strategies
- 🌟 Building automated performance tuning systems with machine learning!
Remember: Process scheduling optimization is key to maximum system performance! You’re now tuning systems like an expert! 🎉
Keep optimizing and you’ll achieve peak performance on Alpine Linux! 💫