Linux Performance Tuning, Kernel Parameters, and Resource Limits
Maximizing Linux server performance requires identifying system bottlenecks (CPU, Memory, Disk I/O, Network), tuning kernel runtime parameters (sysctl), enforcing user/process resource limits (ulimit, cgroups), and profiling latency. This guide covers production performance tuning, kernel configuration, and system profiling.
⚡ Quick Dive
Performance Diagnostics & Tuning Cheat Sheet
| Domain | Command | Action | Example |
|---|---|---|---|
| Kernel Tunables | sysctl -p |
Reload /etc/sysctl.conf or /etc/sysctl.d/*.conf |
sudo sysctl -p /etc/sysctl.d/99-perf.conf |
| Query Parameter | sysctl <param> |
Check active kernel parameter value | sysctl vm.swappiness |
| User Limits | ulimit -n / -u |
View max open files / max user processes | ulimit -n (file descriptors) |
| CPU Priority | nice -n <val> <cmd> |
Launch command with custom niceness (-20 to 19) | nice -n 10 tar -czf backup.tar.gz /data |
| Modify Priority | renice -n <val> -p <pid> |
Change priority of a live running process | sudo renice -n -5 -p 1840 |
| I/O Priority | ionice -c <class> <cmd> |
Launch process with specific I/O scheduler class | ionice -c 3 backup_job.sh (idle class) |
| Memory Bottleneck | vmstat 1 5 |
Monitor memory swapping (si/so) and context switches |
vmstat 1 5 |
| Disk I/O Wait | iostat -xz 1 5 |
Monitor disk saturation (%util) and await latency |
iostat -xz 1 5 |
| Historic Metrics | sar -u 1 5 |
Collect and report historic OS activity (sysstat) | sar -r (memory trends) |
Recommended Production Kernel Profile (/etc/sysctl.d/99-performance.conf)
# Maximize file descriptor & socket allocations
fs.file-max = 2097152
# Reduce memory swapping aggressive paging (default 60; 10 recommended for servers)
vm.swappiness = 10
# Increase incoming network connection backlog queue
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
# Enable TCP BBR Congestion Control (requires Linux 4.9+)
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
# Increase TCP read/write buffer memory (min, default, max in bytes)
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# Enable fast socket reuse for high-throughput proxies
net.ipv4.tcp_tw_reuse = 1
📖 Extended Guide
1. Kernel Runtime Tuning via sysctl
Parameters in /proc/sys/ can be adjusted live using sysctl.
# View active value of a parameter
sysctl vm.max_map_count
# Temporarily modify a parameter in memory
sudo sysctl -w vm.swappiness=10
# Permanently apply changes via drop-in file
sudo sysctl --system
Key Kernel Parameters for Servers:
vm.swappiness(0 to 100):- Controls how aggressively the kernel swaps anonymous RAM pages to disk.
- Default is
60. Set to10on database and application servers to avoid latency spikes while maintaining swap emergency headroom.
vm.dirty_ratio&vm.dirty_background_ratio:- Percentage of system memory that can hold unwritten disk changes before kernel forces writes to disk. Lowering values smooths out I/O spikes.
fs.file-max:- System-wide ceiling for open file handles across all processes.
2. User & Process Resource Limits: ulimit and limits.conf
Operating systems impose limits on the resources consumed by user accounts and processes to prevent Denial-of-Service or accidental fork bombs.
Types of Limits:
- Soft Limit: The value currently enforced by the kernel (can be increased by user up to the hard limit).
- Hard Limit: The ceiling ceiling set by root (cannot be exceeded).
Configuration File: /etc/security/limits.conf
Format: <domain> <type> <item> <value>
# Increase open file descriptors for user 'appuser'
appuser soft nofile 65536
appuser hard nofile 65536
# Increase max processes for group 'developers'
@developers hard nproc 4096
# Set unlimited locked-in-memory size for database engines (Redis/MongoDB)
redis soft memlock unlimited
redis hard memlock unlimited
[!IMPORTANT] Systemd services ignore
/etc/security/limits.conf. To set resource limits for a systemd service, defineLimitNOFILE=65536orLimitNPROC=4096inside the unit file's[Service]block.
3. Process Scheduling Priorities: nice and ionice
CPU Priority with nice
- Niceness ranges from
-20(highest priority, least nice) to19(lowest priority, most nice). - Default process niceness is
0.
# Run CPU-heavy backup task without impacting web server latency
nice -n 19 tar -czf backup.tar.gz /data
# Elevate critical daemon priority (requires root for negative values)
sudo renice -n -10 -p $(pidof haproxy)
Disk I/O Scheduling with ionice
- Class 1 (Real Time): First access to disk.
- Class 2 (Best Effort): Default priority (levels 0-7).
- Class 3 (Idle): Only gets disk access when disk has zero active I/O.
# Run log compressor only when disk is completely idle
ionice -c 3 gzip /var/log/large_dump.sql
4. Identifying Performance Bottlenecks
Bottleneck Symptoms Matrix:
┌─────────────────┬──────────────────────────┬────────────────────────────┐
│ Bottleneck Type │ Diagnostic Tool │ Symptom Trigger │
├─────────────────┼──────────────────────────┼────────────────────────────┤
│ CPU Saturation │ uptime, top, mpstat │ %user + %system near 100% │
│ Memory Starved │ free -h, vmstat 1 │ si (swap in) / so > 0 │
│ Disk I/O Wait │ iostat -xz 1, top │ %wa (iowait) > 10%, %util │
│ File Descriptor │ lsof | wc -l │ "Too many open files" │
└─────────────────┴──────────────────────────┴────────────────────────────┘
Deep Diagnostics Commands
# 1. Inspect per-CPU core utilization
mpstat -P ALL 1 3
# 2. Check which processes are causing disk I/O reads/writes
sudo iotop -o -b -n 3
# 3. Profile CPU cycles and identify kernel/user functions consuming CPU
sudo perf top