近期在一個性能測試項目中遇到了一個調優的過程。分享一下給大家。
1、 第一次打壓時,發現A請求壓力80tps後,cpu佔用就非常高了(24核的機器,每個cpu佔用率全面飆到80%以上),且設置的檢查點沒有任何報錯。
2、 瞭解了一下後臺實現邏輯:大體是這樣的:服務器接到請求後,會再到另一臺kv服務器請求數據,拿回來數據後,根據用戶的機器碼做個性化運算,最後將結果返回給客戶端,期間會輸出一些調試log。
查了下,kv服務器正常,說明是本機服務服務器的問題。具體用vmstat命令看一下異常的地方。
3、 從圖中可以直觀的看出,bi、bo、in、cs這四項的值都很高,根據經驗,bi和bo代表磁盤io相關、in和cs代表系統進程相關。一個一個解決吧,先看io。
4、 用iostat –x命令看了下磁盤讀寫,果然,磁盤慢慢給堵死了。
5、 看了下過程,只有寫log操作才能導致頻繁讀寫磁盤。果斷關閉log。重新打壓試下。
6、 Bi和bo降到正常值了,說明磁盤的問題解決了。但是上下文切換數竟然達到了每秒40萬次!好可怕~
7、 只知道上下文切換數很大,怎麼知道是在哪些進程間切換呢?
到網上搜了一個腳本,這個腳本用來統計特定時間內進程切換的top20並打印出來。
#! /usr/bin/env stap
#
#
global csw_count
global idle_count
probe scheduler.cpu_off {
csw_count[task_prev, task_next]++
idle_count+=idle
}
function fmt_task(task_prev, task_next)
{
return sprintf("%s(%d)->%s(%d)",
task_execname(task_prev),
task_pid(task_prev),
task_execname(task_next),
task_pid(task_next))
}
function print_cswtop () {
printf ("%45s %10s\n", "Context switch", "COUNT")
foreach ([task_prev, task_next] in csw_count- limit 20) {
printf("%45s %10d\n", fmt_task(task_prev, task_next), csw_count[task_prev, task_next])
}
printf("%45s %10d\n", "idle", idle_count)
delete csw_count
delete idle_count
}
probe timer.s($1) {
print_cswtop ()
printf("--------------------------------------------------------------\n")
}
保存成cs.stp後,用stap cswmon.stp 5命令執行下。
8、發現是discover進程在反覆和系統進程進行切換。從此消耗了大量資源。
9、從網上查了下減少切換進程的一些方法:
開發隨後改了下:將線程數開大了一倍,控制在一個進程中。
重新打壓了一下。發現上下文切換數降低到25萬次左右。
此時的性能數據可以達到每秒260次左右,遠遠高於之前的80次。已經達到可以上線的需求。
但是由於頁面中斷書和上下文切換數還是很高,後續還是需要優化~