1. 程式人生 > >磁盤IO高和線程切換過高性能壓測案例分析

磁盤IO高和線程切換過高性能壓測案例分析

cnblogs 左右 系統 stp tex clas ++ class tap

案例現象:

壓力測試的時候,發現A請求壓力80tps後,cpu占用就非常高了(24核的機器,每個cpu占用率全面飆到80%以上),且設置的檢查點沒有任何報錯。

1、top命令如下:

技術分享

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次。已經達到可以上線的需求。

但是由於頁面中斷書和上下文切換數還是很高,後續還是需要優化

磁盤IO高和線程切換過高性能壓測案例分析