LUNAROPS · OPERATIONAL UPLINK 100% UPTIME 1,247d POSTS 893 JEFF.MOON@LUNAROPS.DEV UTC --:--:--

Linux Performance Tuning and Monitoring

linuxperformancetuningmonitoringadvanced

Performance tuning requires understanding bottlenecks and knowing which knobs to turn. This guide covers monitoring, analysis, and optimization.

Performance Methodology

The USE Method

For each resource, check:

  • Utilization: How busy is it?
  • Saturation: Is work queuing?
  • Errors: Are there failures?

Key Resources

Resource Utilization Saturation Errors
CPU top, mpstat Load average, runqueue dmesg
Memory free, vmstat Swapping dmesg, OOM
Disk iostat Wait queue smartctl
Network sar -n DEV Socket backlog ip -s

CPU Performance

Monitoring CPU

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Overall usage
top
htop

# Per-CPU statistics
mpstat -P ALL 1

# Load average
uptime
cat /proc/loadavg
# 1.25 0.87 0.65 2/245 12345
# 1min 5min 15min running/total last_pid

# CPU info
lscpu
cat /proc/cpuinfo

Understanding Load Average

Load average represents average runnable processes:

  • < number of CPUs: System is underutilized
  • = number of CPUs: Fully utilized
  • number of CPUs: Overloaded, processes waiting

1
2
3
# Check CPU count
nproc
grep -c processor /proc/cpuinfo

CPU Bottlenecks

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Find CPU-hungry processes
ps aux --sort=-%cpu | head

# Profile specific process
perf top -p PID
perf record -p PID sleep 30
perf report

# Trace system calls
strace -c command

CPU Tuning

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# CPU frequency scaling
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
echo "performance" | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

# Process affinity
taskset -c 0,1 command      # Run on CPUs 0 and 1
taskset -p -c 0,1 PID       # Set for running process

# Nice value
nice -n 19 command          # Low priority
renice -n -10 -p PID        # Higher priority

Memory Performance

Monitoring Memory

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Overview
free -h

# Detailed statistics
vmstat 1
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
#  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st

# Per-process memory
ps aux --sort=-%mem | head
pmap -x PID

# Memory info
cat /proc/meminfo

Understanding Memory

              total        used        free      shared  buff/cache   available
Mem:           16Gi       4.2Gi       1.5Gi       500Mi      10.3Gi        11Gi
Swap:          2Gi          0B        2Gi
  • used: Actively used
  • buff/cache: File system cache (reclaimable)
  • available: Free + reclaimable cache

Memory Bottlenecks

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Check for swapping
vmstat 1 | awk '{print $7, $8}'  # si, so columns
swapon --show

# OOM killer logs
dmesg | grep -i "out of memory"
journalctl -k | grep -i oom

# Memory leaks
valgrind --leak-check=full ./program

Memory Tuning

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Swappiness (0-100, lower = less swapping)
cat /proc/sys/vm/swappiness
sudo sysctl vm.swappiness=10

# Drop caches (for testing)
sync; echo 3 | sudo tee /proc/sys/vm/drop_caches

# Huge pages
cat /proc/meminfo | grep -i huge
echo 1024 | sudo tee /proc/sys/vm/nr_hugepages

# Per-process limits
ulimit -v unlimited   # Virtual memory

Disk I/O Performance

Monitoring Disk

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Disk activity
iostat -xz 1
# Device  rrqm/s wrqm/s r/s  w/s  rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util

# Per-process I/O
iotop
pidstat -d 1

# Disk usage
df -h
du -sh /path/*

# Filesystem activity
inotifywait -m /path

Understanding iostat

Metric Description Warning
%util Utilization >70%
await Average wait (ms) >10ms
avgqu-sz Queue length >1
r/s, w/s IOPS Depends on disk

Disk Bottlenecks

1
2
3
4
5
6
7
8
# Find I/O heavy processes
iotop -o

# Check disk health
sudo smartctl -a /dev/sda

# Block device info
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,ROTA,DISC-GRAN

Disk Tuning

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# I/O scheduler
cat /sys/block/sda/queue/scheduler
echo "mq-deadline" | sudo tee /sys/block/sda/queue/scheduler

# Read-ahead
blockdev --getra /dev/sda
sudo blockdev --setra 4096 /dev/sda

# Filesystem mount options
# In /etc/fstab, add noatime, nodiratime
/dev/sda1  /  ext4  defaults,noatime  0  1

# SSD TRIM
sudo fstrim -v /

Network Performance

Monitoring Network

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Interface statistics
ip -s link
sar -n DEV 1

# Bandwidth monitoring
iftop
nethogs
bmon

# Connection statistics
ss -s
netstat -s

# TCP analysis
ss -ti

Network Bottlenecks

1
2
3
4
5
6
7
8
# Check for errors/drops
ip -s link show eth0 | grep -E "(errors|dropped)"

# Socket buffer overflows
netstat -s | grep -i overflow

# Connection states
ss -tan | awk '{print $1}' | sort | uniq -c

Network Tuning

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# TCP buffer sizes
sysctl net.core.rmem_max
sysctl net.core.wmem_max

# Increase buffers
sudo sysctl -w net.core.rmem_max=16777216
sudo sysctl -w net.core.wmem_max=16777216
sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
sudo sysctl -w net.ipv4.tcp_wmem="4096 87380 16777216"

# Connection backlog
sudo sysctl -w net.core.somaxconn=65535
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=65535

# TIME_WAIT optimization
sudo sysctl -w net.ipv4.tcp_fin_timeout=15
sudo sysctl -w net.ipv4.tcp_tw_reuse=1

System-Wide Analysis

sar - System Activity Reporter

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# Install sysstat package
sudo apt install sysstat

# Enable data collection
sudo systemctl enable --now sysstat

# CPU history
sar -u

# Memory history
sar -r

# Disk history
sar -d

# Network history
sar -n DEV

# All metrics from specific time
sar -A -s 09:00:00 -e 10:00:00

Performance Co-Pilot (PCP)

1
2
3
4
5
6
7
8
9
# Install
sudo apt install pcp pcp-gui

# Start services
sudo systemctl enable --now pmcd pmlogger

# View metrics
pmstat
pmval kernel.all.load

Kernel Parameters

sysctl

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# View all
sysctl -a

# View specific
sysctl vm.swappiness

# Set temporarily
sudo sysctl vm.swappiness=10

# Set permanently
echo "vm.swappiness=10" | sudo tee /etc/sysctl.d/99-custom.conf
sudo sysctl --system

Common Tuning Parameters

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# /etc/sysctl.d/99-performance.conf

# Memory
vm.swappiness=10
vm.dirty_ratio=15
vm.dirty_background_ratio=5

# Network
net.core.somaxconn=65535
net.core.netdev_max_backlog=65535
net.ipv4.tcp_max_syn_backlog=65535
net.ipv4.tcp_fin_timeout=15
net.ipv4.tcp_tw_reuse=1
net.core.rmem_max=16777216
net.core.wmem_max=16777216

# File descriptors
fs.file-max=2097152

Benchmarking

CPU Benchmark

1
2
3
4
5
# sysbench
sysbench cpu --threads=4 run

# stress-ng
stress-ng --cpu 4 --timeout 60s --metrics-brief

Memory Benchmark

1
sysbench memory --threads=4 run

Disk Benchmark

1
2
3
4
5
6
# Sequential write
dd if=/dev/zero of=testfile bs=1G count=1 oflag=direct

# fio - flexible I/O tester
fio --name=randread --ioengine=libaio --iodepth=16 \
    --rw=randread --bs=4k --direct=1 --size=1G --numjobs=4

Network Benchmark

1
2
3
4
5
6
# iperf3
# Server
iperf3 -s

# Client
iperf3 -c server-ip -t 30

Quick Diagnosis Checklist

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
echo "=== System Overview ==="
uptime
free -h

echo -e "\n=== CPU ==="
mpstat 1 3

echo -e "\n=== Memory ==="
vmstat 1 3

echo -e "\n=== Disk ==="
iostat -xz 1 3

echo -e "\n=== Network ==="
sar -n DEV 1 3

echo -e "\n=== Top Processes (CPU) ==="
ps aux --sort=-%cpu | head -5

echo -e "\n=== Top Processes (Memory) ==="
ps aux --sort=-%mem | head -5

Quick Reference

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# CPU
top, htop, mpstat
perf top -p PID

# Memory
free -h, vmstat, pmap PID

# Disk
iostat -xz, iotop, df -h

# Network
ip -s link, ss -s, iftop

# System-wide
sar, dstat, glances

Performance tuning is iterative: measure, identify bottleneck, tune, measure again. Never tune without understanding the workload.

Comments