Linux 性能優化(四)
- 2020 年 3 月 5 日
- 筆記
CPU 高負責
#top Tasks: 75 total, 2 running, 73 sleeping, 0 stopped, 0 zombie %Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 3881904 total, 2125680 free, 288676 used, 1467548 buff/cache KiB Swap: 0 total, 0 free, 0 used. 3318364 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 188596 3636 2416 S 0.0 0.1 0:28.13 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.07 kthreadd 3 root 20 0 0 0 0 S 0.0 0.0 0:00.42 ksoftirqd/0 5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H 7 root rt 0 0 0 0 S 0.0 0.0 0:00.93 migration/0 8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh 9 root 20 0 0 0 0 S 0.0 0.0 0:20.58 rcu_sched
top 顯示了系統總體的 CPU 和記憶體使用情況,以及各個進程的資源使用情況
但是top 並沒有細分進程的用戶態 CPU 和內核態 CPU
pidstat
用戶態 CPU 使用率 (%usr); 內核態 CPU 使用率(%system); 運行虛擬機 CPU 使用率(%guest); 等待 CPU 使用率(%wait); 以及總的 CPU 使用率(%CPU)。
11:45:40 AM UID PID %usr %system %guest %wait %CPU CPU Command 11:45:41 AM UID PID %usr %system %guest %wait %CPU CPU Command 11:45:42 AM 0 2562 1.00 0.00 0.00 0.00 1.00 1 barad_agent 11:45:42 AM UID PID %usr %system %guest %wait %CPU CPU Command 11:45:43 AM UID PID %usr %system %guest %wait %CPU CPU Command 11:45:44 AM UID PID %usr %system %guest %wait %CPU CPU Command 11:45:45 AM 0 2760 0.00 1.00 0.00 0.00 1.00 0 pidstat Average: UID PID %usr %system %guest %wait %CPU CPU Command Average: 0 2562 0.20 0.00 0.00 0.00 0.20 - barad_agent Average: 0 2760 0.00 0.20 0.00 0.00 0.20 - pidstat
通過 top、ps、pidstat 等工具,你能夠輕鬆找到 CPU 使用率較高(比如 100% )的進程。接下來,佔用 CPU 的到底是程式碼里的哪個函數呢?
只有找到它,才能更高效、更針對性地進行優化。
- GDB(The GNU Project Debugger), 這個功能強大的程式調試利器;但是GDB調試會導致程式中斷,不適合生產環境直接調試
- Linux perf 神器 http://www.brendangregg.com/perf.html,個人比較喜歡這個工具
案例分析

- 使用第一篇文章中提到的機器規格進行實驗
- 安裝docker、sysstat、perf、ab 等工具,如果有興趣可以直接去下載該環境的鏡像 docker.io/feisky/php-fpm和docker.io/feisky/nginx
#docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 545533e3427b feisky/php-fpm "php-fpm -F --pid ..." 5 minutes ago Up 5 minutes phpfpm 2a3f5b5586b5 feisky/nginx "nginx -g 'daemon ..." 5 minutes ago Up 5 minutes 0.0.0.0:10000->80/tcp nginx
#ab -c 10 -n 100 http://192.168.0.10:10000/ Document Path: / Document Length: 9 bytes Concurrency Level: 10 Time taken for tests: 7.206 seconds Complete requests: 100 Failed requests: 0 Write errors: 0 Total transferred: 17200 bytes HTML transferred: 900 bytes Requests per second: 13.88 [#/sec] (mean) Time per request: 720.583 [ms] (mean) Time per request: 72.058 [ms] (mean, across all concurrent requests) Transfer rate: 2.33 [Kbytes/sec] received
使用top看到CPU的使用頻率

每秒的並發只有13.88個,顯然不符合預期
# perf top -g -p 15773
收集perf記錄到本地
在 CentOS 系統中,使用 perf 工具看不到函數名,只能看到一些 16 進位格式的函數地址。其根本原因在於
perf 找不到待分析進程依賴的庫,這裡可以通過指定符號路徑為容器文件系統的路徑
具體方法如下:
#mkdir /tmp/foo # PID=$(docker inspect --format {{.State.Pid}} phpfpm) # bindfs /proc/$PID/root /tmp/foo # perf report --symfs /tmp/foo
使用perf report 分析結果如下:
# perf report --symfs /tmp/foo

注釋掉這段程式碼後
$ cat app/index.php <?php // test only. $x = 0.0001; for ($i = 0; $i <= 1000000; $i++) { $x += sqrt($x); } echo "It works!"
重新啟動容器進行壓測結果如下:

性能百倍增加