【Linux】Linux性能调优实战:从CPU到内存
【Linux】Linux性能调优实战:从CPU到内存
前言
Linux作为服务器领域最流行的操作系统,其性能调优是每个后端工程师必须掌握的技能。无论是运行Web应用、数据库服务还是大数据处理框架,深入理解Linux系统性能瓶颈并加以优化,都能显著提升系统吞吐量和响应速度。作为一名AI程序员,我们经常需要在Linux服务器上进行模型训练、数据处理和服务部署,了解Linux性能调优技术对于提升工作效率具有重要意义。
Linux性能调优是一个系统性工程,涉及CPU、内存、磁盘I/O、网络等多个维度。本文将从实际工作场景出发,详细讲解各子系统的性能分析方法、常见瓶颈识别方法以及具体的优化策略。通过学习本文,读者将能够独立进行Linux系统性能分析和调优工作。
一、Linux性能监控基础
1.1 常用性能监控命令
Linux提供了丰富的性能监控工具,合理使用这些工具是性能分析的第一步。
# top命令:实时监控系统进程和整体资源使用情况 top # 常用选项: # -d seconds: 更新间隔 # -p pid: 监控指定进程 # -H: 显示线程 # -u user: 显示指定用户的进程 # htop命令:增强版的top(需要安装) htop # vmstat命令:虚拟内存统计 vmstat 1 10 # 每秒更新一次,共10次 # 输出: # r: 运行队列中的进程数 # b: 阻塞的进程数 # swpd: 使用的虚拟内存 # free: 空闲内存 # si/so: 换入/换出内存 # us/sy/id/wa: 用户/系统/空闲/等待I/O的CPU时间百分比 # mpstat命令:多处理器统计 mpstat -P ALL 1 5 # 显示所有CPU核心的统计信息 # iostat命令:CPU和磁盘I/O统计 iostat -xz 1 5 # 输出: # %util: 设备利用率,接近100%表示I/O瓶颈 # await: I/O请求平均等待时间 # avgqu-sz: 平均请求队列长度 # svctm: 平均服务时间 # free命令:内存使用情况 free -h # -h人性化显示 free -m # 以MB为单位显示 # 输出: # total: 总内存 # used: 已使用 # free: 空闲 # shared: 共享内存 # buffers/cached: 缓存 # available: 可用内存(更准确的指标)1.2 进程监控与分析
# ps命令:查看进程状态 ps aux # 显示所有进程 ps -ef # 标准格式显示 ps -eo pid,ppid,user,%cpu,%mem,cmd --sort=-%cpu # 按CPU使用率排序 # 查看特定进程的信息 ps -p $(pgrep -f "python") -o pid,%cpu,%mem,cmd # 查看线程信息 ps -eLf | grep python # 显示Python进程的所有线程 pstree -p $(pgrep -f process_name) # 显示进程树 # top命令中常用的交互式快捷键 # P: 按CPU排序 # M: 按内存排序 # T: 按时间排序 # c: 显示完整命令 # k: 杀死进程 # 1: 切换显示单个/所有CPU核心1.3 性能监控脚本
#!/bin/bash # system_monitor.sh - 系统性能监控脚本 # 设置监控间隔(秒) INTERVAL=5 echo "=== Linux System Performance Monitor ===" echo "Monitoring interval: ${INTERVAL}s" echo "Press Ctrl+C to stop" echo "" # 循环监控 while true; do echo "========================================" echo "Time: $(date '+%Y-%m-%d %H:%M:%S')" echo "----------------------------------------" # CPU使用率 echo "CPU Usage:" mpstat 1 1 | grep -A 5 "Average" || true top -bn1 | grep "Cpu(s)" | awk '{print "Total CPU: " $2 + $4 "%"}' echo "" echo "Memory Usage:" free -h | grep Mem | awk '{printf "Used: %s / Total: %s (%.1f%%)\n", $3, $2, ($3/$2)*100}' echo "" echo "Top 5 CPU Processes:" ps -eo pid,user,%cpu,%mem,cmd --sort=-%cpu | head -6 echo "" echo "Top 5 Memory Processes:" ps -eo pid,user,%cpu,%mem,cmd --sort=-%mem | head -6 echo "" echo "Disk I/O:" iostat -xz 1 1 2>/dev/null | tail -n +7 | head -5 || echo "iostat not available" echo "" echo "Network I/O:" cat /proc/net/dev | grep -E "eth0|ens33|ens160" | awk '{printf "Interface %s: RX=%d bytes, TX=%d bytes\n", $1, $2, $10}' sleep $INTERVAL done二、CPU性能调优
2.1 CPU性能指标分析
理解CPU性能指标是调优的基础:
# 查看CPU信息 cat /proc/cpuinfo lscpu nproc # CPU核心数 # CPU使用率的构成 # us: 用户空间进程使用的CPU时间 # sy: 内核空间使用的CPU时间 # ni: nice值调整过的进程使用的CPU时间 # id: 空闲时间 # wa: 等待I/O完成的时间 # hi: 硬件中断处理时间 # si: 软件中断处理时间 # st: 被虚拟机偷走的时间 # 分析CPU瓶颈 # 1. 如果us过高:应用程序计算量大,考虑优化算法或增加CPU # 2. 如果sy过高:系统调用频繁,考虑减少系统调用或优化I/O # 3. 如果wa过高:磁盘I/O瓶颈,需要优化存储或增加缓存 # 4. 如果hi/si过高:中断处理过多,检查硬件或驱动问题2.2 进程CPU使用率优化
# 查看进程的CPU使用详情 # 方法1:使用ps命令 ps -p PID -o pid,%cpu,%mem,cmd # 方法2:使用top top -p PID # 方法3:使用pidstat(需要安装sysstat包) pidstat -p PID 1 5 # 每秒采样一次,共5次 # 方法4:使用/proc文件系统 cat /proc/PID/stat | awk '{print "utime: " $14/100 "s, stime: " $15/100 "s"}' # 查看进程的线程CPU使用 pidstat -p PID -t 1 3 # 显示线程统计2.3 CPU亲和性配置
CPU亲和性允许我们将进程绑定到特定的CPU核心,减少上下文切换:
# taskset命令:设置CPU亲和性 # 将进程绑定到CPU核心0 taskset -cp 0,1 PID # 绑定到核心0和1 # 查看进程的CPU亲和性 taskset -cp PID # 使用掩码设置亲和性 taskset -cp 0x55 PID # 二进制掩码,0x55 = 01010101,绑定到核心0,2,4,6 # numactl命令:更高级的NUMA控制 numactl --cpunodebind=0 --membind=0 python script.py # 绑定到节点0 # 查看NUMA配置 numactl --hardware numastat2.4 进程优先级调整
# nice值:-20(最高优先级)到19(最低优先级) # renice命令:调整运行中进程的优先级 renice -n 10 -p PID # 将PID进程的nice值调整为10 # nice命令:启动时设置优先级 nice -n -5 ./my_program # 以高优先级启动 # 查看进程优先级 ps -eo pid,ni,cmd | grep process_name # 实时调整进程优先级(需要root) # 在top中按r,输入PID,再输入nice值三、内存性能调优
3.1 内存性能指标分析
# 查看内存使用详情 cat /proc/meminfo # 关键指标解读: # MemTotal: 总内存 # MemFree: 空闲内存 # MemAvailable: 可用内存(更准确,包含可回收内存) # Buffers: 缓冲区 # Cached: 页面缓存 # SwapTotal: 交换分区总大小 # SwapFree: 交换分区空闲大小 # Dirty: 等待写回的内存 # Writeback: 正在写回的内存 # 页面缓存回收配置 # dirty_ratio: 触发强制写回的比例 # dirty_background_ratio: 后台写回开始的比例 # dirty_expire_centisecs: 脏数据过期时间(百分之一秒) # dirty_writeback_centisecs: 后台写回间隔 # 查看内存使用趋势 vmstat 1 10 # 详细的内存统计 cat /proc/vmstat | grep -E "pgpgin|pgpgout|pswpin|pswpout|pgfault" # pgpgin/pgpgout: 页面换入/换出 # pswpin/pswpout: 交换空间换入/换出 # pgfault: 页面错误数3.2 内存泄漏检测
# 方法1:使用ps命令对比内存使用 ps aux --sort=-%mem | head -10 sleep 60 ps aux --sort=-%mem | head -10 # 对比 # 方法2:使用pmap查看进程内存映射 pmap -x PID # -x显示扩展格式 # 方法3:使用valgrind检测内存泄漏 valgrind --leak-check=full ./program # 方法4:使用 AddressSanitizer(编译器级别) # 编译时添加 -fsanitize=address gcc -fsanitize=address -g program.c -o program # 方法5:使用/proc/[pid]/smaps查看详细内存信息 cat /proc/PID/smaps | grep -A 2 "heap" # 查看内存分配的堆栈跟踪 cat /proc/PID/maps3.3 内存优化配置
# /etc/sysctl.conf 中的内存相关配置 # 虚拟内存配置 vm.swappiness=10 # 交换分区使用倾向(0-100),值越低越少使用swap vm.dirty_ratio=15 # 触发强制写回的脏页比例 vm.dirty_background_ratio=5 # 后台写回开始的脏页比例 vm.dirty_expire_centisecs=500 # 脏页过期时间(1/100秒) vm.dirty_writeback_centisecs=100 # 后台写回间隔 # 文件系统缓存配置 vm.vfs_cache_pressure=50 # 内核回收缓存的倾向(100为默认,越小越保留缓存) # 共享内存配置 kernel.shmmax=6843596288 # 最大共享内存段大小 kernel.shmall=4294967296 # 共享内存总页数 # 应用示例:生效配置 sudo sysctl -p # 临时修改(重启后失效) sudo sysctl -w vm.swappiness=103.4 大页内存配置
# 查看大页配置 cat /proc/meminfo | grep -i huge # 配置透明大页(THP,CentOS/RHEL 7+) echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag # 永久配置:在/etc/rc.d/rc.local中添加上述命令 # 为数据库等应用配置专用大页 # 在/etc/sysctl.conf中配置 vm.nr_hugepages=256 # 分配256个大页(每个2MB) # 查看当前大页使用情况 cat /proc/meminfo | grep -i huge四、磁盘I/O性能调优
4.1 I/O性能监控与分析
# iostat命令详解 iostat -x 1 5 # 关键指标: # %util: 设备利用率,>80%表示I/O繁忙 # r/s, w/s: 每秒读写请求数 # rkB/s, wkB/s: 每秒读写KB数 # await: 平均等待时间(毫秒) # avgqu-sz: 平均队列长度 # svctm: 平均服务时间(已废弃,不可靠) # 查看I/O等待 iostat -x | awk '/^Device/ {device=$1} /^[s,v]da/ {if($NF>80) print device, $NF"%"}' # 查看进程的I/O统计 pidstat -d 1 3 # 磁盘I/O统计 pidstat -p PID -d 1 3 # 特定进程 # 查看实际I/O操作 iotop # 需要root # 安装:sudo apt install iotop # 查看块设备队列 cat /sys/block/sda/queue/nr_requests # 请求队列长度 cat /sys/block/sda/queue/read_ahead_kb # 预读KB数 cat /sys/block/sda/queue/scheduler # I/O调度器 # 查看I/O调度器 cat /sys/block/*/queue/scheduler # 调度器类型: # cfq: 完全公平队列(适合桌面和通用服务器,正在被淘汰) # deadline: 期限调度(适合数据库等延迟敏感场景) # noop: 空操作(适合SSD或虚拟化环境) # mq-deadline: 多队列期限调度(现代SSD推荐)4.2 I/O调度器配置
# 查看当前调度器 cat /sys/block/sda/queue/scheduler # 临时修改调度器 echo deadline > /sys/block/sda/queue/scheduler # 永久修改:在/etc/default/grub中添加 # GRUB_CMDLINE_LINUX="elevator=deadline" # 然后执行 sudo update-grub # 针对SSD的优化配置 echo none > /sys/block/sda/queue/scheduler # SSD不需要调度器 echo mq-deadline > /sys/block/sda/queue/scheduler # 或使用多队列deadline # 调整队列深度 echo 4096 > /sys/block/sda/queue/nr_requests # 调整预读 blockdev --setra 4096 /dev/sda # 设置预读为4MB4.3 文件系统优化
# 选择合适的文件系统 # ext4: 通用,适合大多数场景 # xfs: 大文件和高并发,RHEL/CentOS默认 # btrfs: 高级特性(快照、压缩),但生产环境需谨慎 # zfs: 高级特性,适合存储服务器 # 挂载选项优化 # 在/etc/fstab中配置 # /dev/sda1 /data ext4 defaults,noatime,nodiratime,errors=remount-ro 0 1 # 常用挂载选项: # noatime: 不更新访问时间(适合频繁读取的场景) # nodiratime: 不更新目录访问时间 # relatime: 合理更新访问时间(折中方案) # data=journal: journaling模式(ext4),提高可靠性但降低性能 # barrier=0: 禁用屏障(需要RAID卡有电池保护) # 查看文件系统的详细信息 dumpe2fs -h /dev/sda1 # ext4 xfs_info /dev/sda1 # xfs # 文件系统检查 # ext4: fsck.ext4 -f /dev/sda1 # xfs: xfs_repair /dev/sda14.4 使用tmpfs提升性能
# tmpfs是基于内存的文件系统,适合临时文件 # 查看当前tmpfs使用 df -h | grep tmpfs # 挂载tmpfs mount -t tmpfs -o size=4G tmpfs /tmp # 在/etc/fstab中添加: # tmpfs /tmp tmpfs defaults,size=4G,mode=1777 0 0 # 常见应用场景: # - /tmp 目录 # - 应用的临时缓存目录 # - 编译时的中间文件 # 注意:数据不持久化,需要确保数据已保存五、网络性能调优
5.1 网络性能监控
# 查看网络接口统计 cat /proc/net/dev ip -s link show # 查看TCP/UDP统计 netstat -s ss -s # 查看连接状态分布 ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn # 带宽测量 # 安装 iperf3 # 服务器端:iperf3 -s # 客户端:iperf3 -c server_ip -t 30 # 网络延迟测量 ping -c 10 server.example.com traceroute server.example.com # 或 mtr # 查看网络连接对应的进程 ss -tlnp | grep :80 # 查看80端口的监听进程5.2 内核网络参数调优
# /etc/sysctl.conf 中的网络配置 # TCP连接相关 net.ipv4.tcp_tw_reuse=1 # 允许重用TIME_WAIT状态的连接 net.ipv4.tcp_fin_timeout=30 # FIN超时时间 net.ipv4.tcp_keepalive_time=600 # Keepalive检测间隔 net.ipv4.tcp_keepalive_probes=3 # Keepalive探测次数 net.ipv4.tcp_keepalive_intvl=15 # Keepalive探测间隔 # 缓冲区大小 net.core.rmem_max=134217728 # 最大接收缓冲区 net.core.wmem_max=134217728 # 最大发送缓冲区 net.ipv4.tcp_rmem=4096 87380 134217728 # TCP接收缓冲区 net.ipv4.tcp_wmem=4096 65536 134217728 # TCP发送缓冲区 # 连接队列 net.core.somaxconn=65535 # 监听队列最大长度 net.ipv4.tcp_max_syn_backlog=65535 # SYN队列长度 # 其他优化 net.ipv4.conf.all.forwarding=1 # 启用IP转发 net.ipv4.conf.default.forwarding=1 net.core.netdev_max_backlog=65535 # 网络设备积压队列 net.ipv4.tcp_no_metrics_save=1 # 不保存连接度量到缓存 # 生效配置 sudo sysctl -p # 临时修改 sudo sysctl -w net.core.somaxconn=655355.3 网络接口优化
# 查看和设置网卡参数 ethtool eth0 # 查看统计信息 ethtool -S eth0 # 常见的网卡优化设置 ethtool -G eth0 rx 4096 tx 4096 # 设置环形缓冲区大小 ethtool -C eth0 rx-usecs 100 tx-usecs 100 # 中断合并 # 开启网卡多队列 ethtool -L eth0 combined 4 # 查看网卡队列 cat /proc/interrupts | grep eth0 # 绑定中断到CPU # 查看当前中断亲和性 cat /proc/irq/XX/smp_affinity # 设置中断亲和性(十六进制掩码) echo 01 > /proc/irq/XX/smp_affinity # 绑定到CPU 0 echo 02 > /proc/irq/XX/smp_affinity # 绑定到CPU 15.4 连接追踪优化
# 查看连接跟踪表 cat /proc/net/nf_conntrack sudo conntrack -L # 最大连接跟踪数 cat /proc/sys/net/netfilter/nf_conntrack_max # 设置最大连接跟踪数 echo 262144 > /proc/sys/net/netfilter/nf_conntrack_max # 超时时间优化 cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established # 在/etc/sysctl.conf中配置 net.netfilter.nf_conntrack_max=262144 net.netfilter.nf_conntrack_tcp_timeout_established=7200六、综合调优实战案例
6.1 Web服务器(Nginx)调优
# /etc/nginx/nginx.conf worker_processes auto; # 自动设置与CPU核心数一致 worker_rlimit_nofile 65535; # 打开文件描述符限制 events { worker_connections 10240; # 每个worker的连接数 use epoll; # Linux高性能事件模型 multi_accept on; # 一次接受多个连接 } http { # 基础优化 sendfile on; tcp_nopush on; tcp_nodelay on; # Keepalive设置 keepalive_timeout 65; keepalive_requests 10000; # Gzip压缩 gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css application/json application/javascript; # 缓冲区设置 client_body_buffer_size 10K; client_header_buffer_size 1k; client_max_body_size 8m; large_client_header_buffers 4 32k; # 超时设置 client_body_timeout 12; client_header_timeout 12; send_timeout 10; # 连接复用 upstream backend { server 127.0.0.1:8001; server 127.0.0.1:8002; keepalive 32; # Keepalive连接数 } }6.2 数据库服务器调优
# /etc/mysql/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf [mysqld] # InnoDB缓冲池大小(建议为服务器内存的60-80%) innodb_buffer_pool_size=8G innodb_buffer_pool_instances=8 # 多实例,减少锁竞争 # 日志配置 innodb_log_file_size=1G innodb_log_files_in_group=3 innodb_flush_log_at_trx_commit=1 # 1=安全,2=性能,0=最快 # 并发配置 innodb_thread_concurrency=0 # 0=不限制,由InnoDB自动调整 innodb_read_io_threads=8 innodb_write_io_threads=8 innodb_io_capacity=2000 innodb_io_capacity_max=4000 # 临时表和排序 tmp_table_size=256M max_heap_table_size=256M sort_buffer_size=4M join_buffer_size=4M # 连接数 max_connections=500 wait_timeout=600 interactive_timeout=600 # 慢查询日志 slow_query_log=1 slow_query_log_file=/var/log/mysql/slow.log long_query_time=1 # 缓存 query_cache_type=0 # MySQL 8.0已移除,忽略此设置6.3 Python应用进程管理
#!/bin/bash # start_python_app.sh - Python应用启动脚本 export PYTHONUNBUFFERED=1 export OMP_NUM_THREADS=4 # OpenMP线程数 # 进程数(建议为2-4倍CPU核心数) WORKERS=8 # 每个进程的线程数(对于I/O密集型可以更多) THREADS=2 # 超时时间 TIMEOUT=30 # 绑定到特定CPU核心(可选) # CPU_MASK="0,1,2,3" # 使用gunicorn启动 # gunicorn是Python WSGI服务器,支持多worker exec gunicorn \ --workers $WORKERS \ --threads $THREADS \ --timeout $TIMEOUT \ --bind 0.0.0.0:8000 \ --worker-class uvicorn.workers.UvicornWorker \ --access-logfile /var/log/app/access.log \ --error-logfile /var/log/app/error.log \ --log-level info \ --max-requests 1000 \ --max-requests-jitter 50 \ app:app6.4 完整系统调优脚本
#!/bin/bash # optimize_system.sh - Linux系统性能调优脚本 set -e echo "=== Linux System Performance Optimization ===" # 检查是否为root if [ "$EUID" -ne 0 ]; then echo "Please run as root" exit 1 fi # 备份当前配置 BACKUP_DIR="/tmp/sys_backup_$(date +%Y%m%d_%H%M%S)" mkdir -p $BACKUP_DIR cp -r /etc/sysctl.conf $BACKUP_DIR/ 2>/dev/null || true cp -r /etc/security/limits.conf $BACKUP_DIR/ 2>/dev/null || true echo "Backup saved to: $BACKUP_DIR" # 优化内核参数 cat >> /etc/sysctl.conf << 'EOF' # === Performance Optimization === # Network net.core.somaxconn=65535 net.core.netdev_max_backlog=65535 net.ipv4.tcp_max_syn_backlog=65535 net.ipv4.tcp_fin_timeout=30 net.ipv4.tcp_tw_reuse=1 net.ipv4.tcp_keepalive_time=600 net.ipv4.tcp_keepalive_probes=3 net.ipv4.tcp_keepalive_intvl=15 # Memory vm.swappiness=10 vm.dirty_ratio=15 vm.dirty_background_ratio=5 vm.dirty_expire_centisecs=500 vm.vfs_cache_pressure=50 # File System fs.file-max=2097152 fs.inotify.max_user_instances=524288 fs.inotify.max_user_watches=524288 EOF # 生效配置 sysctl -p # 优化文件描述符限制 cat >> /etc/security/limits.conf << 'EOF' # === Performance Optimization === * soft nofile 2097152 * hard nofile 2097152 * soft nproc 65535 * hard nproc 65535 EOF # 优化网络(如果使用systemd) if [ -d /etc/systemd ]; then mkdir -p /etc/systemd/system.conf.d/ cat > /etc/systemd/system.conf.d/performance.conf << 'EOF' [Manager] DefaultLimitNOFILE=2097152 DefaultLimitNPROC=65535 EOF fi echo "=== Optimization Complete ===" echo "Please reboot for full effect"七、性能问题排查方法论
7.1 排查流程
当遇到性能问题时,应该按照以下流程排查:
- 确认问题:确定是CPU、内存、磁盘还是网络问题
- 收集数据:使用监控工具收集性能数据
- 分析瓶颈:找出性能瓶颈的根本原因
- 制定方案:制定优化方案
- 实施优化:执行优化操作
- 验证效果:确认优化效果
# 快速定位问题类型 # 1. 运行top,按Shift+O,再按1查看CPU核心使用情况 # 2. 如果CPU使用率高,问题在CPU # 3. 如果CPU使用率低但负载高,问题在I/O # 4. 如果内存使用率高但交换区使用低,说明应用需要更多内存 # 5. 如果交换区使用率高,说明内存不足 # 使用uptime快速查看负载 uptime # 输出:load average: 0.5, 0.8, 1.2 # 三个数字分别是1分钟、5分钟、15分钟的平均负载 # 如果负载大于CPU核心数,说明有性能瓶颈7.2 常用排查命令速查表
# CPU问题 top -bn1 | head -20 # 查看高CPU进程 pidstat -p PID 1 10 # 监控特定进程 ps -eo pid,pcpu,cmd --sort=-pcpu | head # 按CPU排序 # 内存问题 free -h # 查看内存使用 ps -eo pid,pmem,cmd --sort=-pmem | head # 按内存排序 cat /proc/meminfo | grep -E "Swap|Cache" # 查看缓存和交换 # I/O问题 iostat -xz 1 10 # 查看磁盘I/O iotop # 查看I/O占用 pidstat -d 1 5 # 查看进程I/O # 网络问题 ss -tuln # 查看监听端口 netstat -anp | grep ESTABLISHED # 查看活动连接 cat /proc/net/sockstat # 查看套接字统计八、总结
Linux性能调优是一个系统性的工程,需要综合考虑CPU、内存、磁盘I/O和网络等多个方面。本文介绍了:
- 性能监控基础:掌握top、vmstat、iostat等常用监控命令
- CPU调优:理解CPU指标、合理设置优先级和亲和性
- 内存调优:分析内存使用、检测内存泄漏、优化配置
- 磁盘I/O调优:选择合适的调度器、优化文件系统
- 网络调优:调整内核参数、优化网卡配置
- 实战案例:Web服务器、数据库、应用进程的具体优化
性能调优的关键是:
- 先监控分析,再针对性优化
- 每次只改一个参数,便于定位效果
- 记录优化前后的数据,验证优化效果
- 理解原理比记住命令更重要
希望本文能够帮助读者建立起完整的Linux性能调优知识体系,在实际工作中有效提升系统性能。
