精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

系統(tǒng)性能分析從入門到進(jìn)階

原創(chuàng) 精選
開發(fā) 前端
本文以系統(tǒng)為中心, 結(jié)合日常工作和用例, 由淺入深地介紹了性能分析的一些方法和體會, 希望對想了解系統(tǒng)性能分析的同學(xué)有所幫助。

作者| 勿非

一、入門篇

1.資源角度

USE

產(chǎn)品跑在系統(tǒng)的各種資源上面, 從系統(tǒng)資源的角度入門性能分析是個(gè)不錯(cuò)的選擇, 我們以業(yè)界知名大牛Brendan Gregg的USE方法開始, USE特點(diǎn)就是簡單有效適合入門, 用Brendan的話描述USE的效果:

I find it solves about 80% of server issues with 5% of the effort.

USE從系統(tǒng)資源的角度, 包括但不限于CPU, 內(nèi)存, 磁盤, 網(wǎng)絡(luò)等, 關(guān)注以下3個(gè)方面

  • Utilization (U): as a percent over a time interval. eg, "one disk is running at 90% utilization". 大多數(shù)情況可以合理推測利用率高可能會影響性能。
  • Saturation (S): as a queue length. eg, "the CPUs have an average run queue length of four". 資源競爭的激烈程度。
  • Errors (E). scalar counts. eg, "this network interface has had fifty late collisions". Errors相對直觀。

CPU

對于CPU, 主要關(guān)注以下指標(biāo):

  • Utilization. CPU的利用率。
  • Saturation. 可以是load average, runqueue length, sched latency等。

CPU利用率用top看下

top - 17:13:49 up 83 days, 23:10,  1 user,  load average: 433.52, 422.54, 438.70
Tasks: 2765 total, 23 running, 1621 sleeping, 0 stopped, 34 zombie
%Cpu(s): 23.4 us, 9.5 sy, 0.0 ni, 65.5 id, 0.7 wa, 0.0 hi, 1.0 si, 0.0 st

CPU利用率拆分成了更細(xì)粒度的幾部分

  • us, sys, ni - 對應(yīng)un-niced user, kernel, niced user的CPU利用率。
  • id, wa - 對應(yīng)到idle, io wait的比例, io wait本質(zhì)上也是一種idle, 區(qū)別在于對應(yīng)cpu上有等待io的任務(wù)
  • hi, si - 對應(yīng)hardirq, softirq的比例。
  • st - 因?yàn)槌u等原因, hypervisor從該vm偷走的時(shí)間 (todo: docker)

繼續(xù)看load average, 3個(gè)數(shù)值分別對應(yīng)到系統(tǒng)1/5/15分鐘內(nèi)的系統(tǒng)平均load, load是個(gè)比較模糊的概念, 可以簡單認(rèn)為是對資源有需求的任務(wù)數(shù), 包括on cpu, runnable的任務(wù), 也包括等待IO及任意D狀態(tài)的任務(wù). load使用采樣的方式, 每隔5秒采樣一樣, 越近的采樣權(quán)重越大, 這樣從1/5/15的趨勢可以看出系統(tǒng)壓力的變化。

load average: 433.52, 422.54, 438.70

在這臺128個(gè)CPU的機(jī)器上, loadavg看起來有些偏高, 但是具體影響目前不得而知, 性能低是相對具體目標(biāo)而言的, load高只是現(xiàn)象, 它可能相關(guān)也可能無關(guān), 但至少是值得注意的。

再看下dstat關(guān)于任務(wù)狀態(tài)的統(tǒng)計(jì)

  • run - 對應(yīng)到/proc/stat里面的procs_running, 也就是runnable任務(wù)數(shù)。
  • blk - 對應(yīng)到/proc/stat里面的procs_blocked, 阻塞在I/O的任務(wù)數(shù)。

實(shí)際上和loadavg沒有本質(zhì)區(qū)別, 只是load模糊了runnable和D狀態(tài), 同時(shí)load使用1/5/15分鐘的力度, 而dstat可以使用更細(xì)粒度, 如果只看某一時(shí)間點(diǎn)用load, 如果要觀察長時(shí)間的變化使用dstat (/proc/stat)。

#dstat -tp
----system---- ---procs---
time |run blk new
07-03 17:56:50|204 1.0 202
07-03 17:56:51|212 0 238
07-03 17:56:52|346 1.0 266
07-03 17:56:53|279 5.0 262
07-03 17:56:54|435 7.0 177
07-03 17:56:55|442 3.0 251
07-03 17:56:56|792 8.0 419
07-03 17:56:57|504 16 152
07-03 17:56:58|547 3.0 156
07-03 17:56:59|606 2.0 212
07-03 17:57:00|770 0 186

內(nèi)存

這里主要關(guān)注內(nèi)存容量方面, 不關(guān)注訪存的性能。

  • Utilization. 內(nèi)存利用率
  • Saturation. 這里主要考察內(nèi)存回收算法的效率。

簡單的內(nèi)存利用率用free命令

  • total - MemTotal + SwapTotal, 一般來說MemTotal會略小于真實(shí)的物理內(nèi)存。
  • free - 未使用的內(nèi)存. Linux傾向于緩存更多頁面以提高性能, 所以不能簡通過free來判斷內(nèi)存是否不足
  • buff/cache - 系統(tǒng)緩存, 一般不需要嚴(yán)格區(qū)分buffer和cache。
  • available - 估計(jì)的可用物理內(nèi)存大小。
  • used - 等于total - free - buffers - cache。
  • Swap - 該機(jī)器上未配置。
#free -g
total used free shared buff/cache available
Mem: 503 193 7 2 301 301
Swap: 0 0 0

更詳細(xì)的信息可以直接去讀/proc/meminfo

#cat /proc/meminfo
MemTotal: 527624224 kB
MemFree: 8177852 kB
MemAvailable: 316023388 kB
Buffers: 23920716 kB
Cached: 275403332 kB
SwapCached: 0 kB
Active: 59079772 kB
Inactive: 431064908 kB
Active(anon): 1593580 kB
Inactive(anon): 191649352 kB
Active(file): 57486192 kB
Inactive(file): 239415556 kB
Unevictable: 249700 kB
Mlocked: 249700 kB
SwapTotal: 0 kB
SwapFree: 0 kB
[...]

再來看下內(nèi)存回收相關(guān)的信息, sar的數(shù)據(jù)主要從/proc/vmstat采集, 主要關(guān)注

  • pgscank/pgscand - 分別對應(yīng)kswapd/direct內(nèi)存回收時(shí)掃描的page數(shù)。
  • pgsteal - 回收的page數(shù)
  • %vmeff - pgsteal/(pgscank+pgscand)

要理解這些數(shù)據(jù)的具體含義, 需要對內(nèi)存管理算法有一定了解, 比如這里的pgscan/pgsteal只是針對inactive list而言的, 在內(nèi)存回收的時(shí)候可能還需要先把頁面從active list搬到inactive list等. 如果這里有異常, 我們可以先把這當(dāng)成入口, 再慢慢深入, 具體到這里的%vmeff, 最好情況就是每個(gè)掃描的page都能回收, 也就是vmeff越高越好。

#sar -B 1

11:00:16 AM pgscank/s pgscand/s pgsteal/s %vmeff
11:00:17 AM 0.00 0.00 3591.00 0.00
11:00:18 AM 0.00 0.00 10313.00 0.00
11:00:19 AM 0.00 0.00 8452.00 0.00

I/O

存儲I/O的USE模型

  • Utilization. 存儲設(shè)備的利用率, 單位時(shí)間內(nèi)設(shè)備在處理I/O請求的時(shí)間。
  • Saturation. 隊(duì)列長度。

我們一般關(guān)注這些部分

  • %util - 利用率. 注意即使達(dá)到100%的util, 也不代表設(shè)備沒有性能余量了, 特別地現(xiàn)在的SSD盤內(nèi)部都支持并發(fā). 打個(gè)比方, 一家旅館有10間房, 每天只要有1個(gè)房間入住, util就是100%。
  • svctm - 新版iostat已經(jīng)刪掉
  • await/r_await/w_await - I/O延遲, 包括排隊(duì)時(shí)間。
  • avgrq-sz - 平均request size, 請求處理時(shí)間和大小有一定關(guān)系, 不一定線性。
  • argqu-sz - 評估queue size, 可以用來判斷是否有積壓。
  • rMB/s, wMB/s, r/s, w/s - 基本語義

資源粒度

當(dāng)我們判斷資源是否是瓶頸的時(shí)候, 只看系統(tǒng)級別的資源是不夠的, 比如可以用htop看下每個(gè)CPU的利用率, 目標(biāo)任務(wù)運(yùn)行在不同CPU上的性能可能相差很大。

內(nèi)存也有類似情況, 運(yùn)行numastat -m

                          Node 0          Node 1          Node 2          Node 3
--------------- --------------- --------------- ---------------
MemTotal 31511.92 32255.18 32255.18 32255.18
MemFree 2738.79 131.89 806.50 10352.02
MemUsed 28773.12 32123.29 31448.69 21903.16
Active 7580.58 419.80 9597.45 5780.64
Inactive 17081.27 26844.28 19806.99 13504.79
Active(anon) 6.63 0.93 2.08 5.64
Inactive(anon) 12635.75 25560.53 12754.29 9053.80
Active(file) 7573.95 418.87 9595.37 5775.00
Inactive(file) 4445.52 1283.75 7052.70 4450.98

系統(tǒng)不一定就是物理機(jī), 如果產(chǎn)品跑在cgroup, 那么這個(gè)cgroup是更需要關(guān)注的系統(tǒng), 比如在空閑系統(tǒng)上執(zhí)行如下命令

#mkdir /sys/fs/cgroup/cpuset/overloaded
#echo 0-1 > /sys/fs/cgroup/cpuset/cpuset.cpus
#echo 0 > /sys/fs/cgroup/cpuset/cpuset.mems
#echo $$
#for i in {0..1023}; do /tmp/busy & done

此時(shí)從物理機(jī)級別看, 系統(tǒng)的load很高, 但是因?yàn)閏puset的限制, 競爭約束在cpu 0和1上, 對運(yùn)行在其他cpu上的產(chǎn)品影響并不大。

#uptime
14:10:54 up 6 days, 18:52, 10 users, load average: 920.92, 411.61, 166.95

2.應(yīng)用角度

系統(tǒng)資源和應(yīng)用的性能可能會有某種關(guān)聯(lián), 但是也可以更直接地從應(yīng)用的角度出發(fā)定位問題

  • 應(yīng)用能使用多少資源, 而不是系統(tǒng)提供了多少資源, 這里面可能會有g(shù)ap, 系統(tǒng)是個(gè)模糊的概念, 而應(yīng)用本身卻相對具體. 以上面cpuset為例, 物理機(jī)是個(gè)系統(tǒng)cpuset管理的資源也可以成為系統(tǒng), 但是應(yīng)用在cpuset里面還是外面是確定的。
  • 應(yīng)用對資源的需求, 即使系統(tǒng)資源再多, 應(yīng)用用不上性能也上不去, 也就是系統(tǒng)可能沒問題, 而是應(yīng)用本身的原因。

以下面的myserv為例, 它的4個(gè)線程%cpu都達(dá)到了100, 這個(gè)時(shí)候再去分析整個(gè)系統(tǒng)的load什么用處不大, 系統(tǒng)有再多的空閑cpu對myserv來說已經(jīng)沒有意義。

#pidstat -p `pgrep myserv` -t 1
15:47:05 UID TGID TID %usr %system %guest %CPU CPU Command
15:47:06 0 71942 - 415.00 0.00 0.00 415.00 22 myserv
15:47:06 0 - 71942 0.00 0.00 0.00 0.00 22 |__myserv
...
15:47:06 0 - 72079 7.00 94.00 0.00 101.00 21 |__myserv
15:47:06 0 - 72080 10.00 90.00 0.00 100.00 19 |__myserv
15:47:06 0 - 72081 9.00 91.00 0.00 100.00 35 |__myserv
15:47:06 0 - 72082 5.00 95.00 0.00 100.00 29 |__myserv

3.常用命令

基本命令

基本命令一般用來讀取內(nèi)核中記錄的各種統(tǒng)計(jì)信息, 特別是/proc下面的各種文件, 這里簡單列舉部分

  • top - 提供了交互模式和batch模式, 不帶參數(shù)進(jìn)入交互模式, 按下h鍵可以看到各種功能。
  • ps - 提供了各種參數(shù)查看系統(tǒng)中任務(wù)的狀態(tài), 比如ps aux或者ps -eLf, 很多參數(shù)可以在需要的時(shí)候查看手冊。
  • free - 內(nèi)存信息。
  • iostat - I/O性能
  • pidstat - 查看進(jìn)程相關(guān)的信息, 上面已經(jīng)介紹過。
  • mpstat - 可以查看單獨(dú)cpu的利用率, softirq, hardirq個(gè)數(shù)等。
  • vmstat - 可以查看虛擬內(nèi)存及各種系統(tǒng)信息。
  • netstat - 網(wǎng)絡(luò)相關(guān)
  • dstat - 可以查看cpu/disk/mem/net等各種信息, 這些stat命令哪個(gè)方便用哪個(gè)。
  • htop - 上面介紹過。
  • irqstat - 方便觀察中斷信息。
  • sar/tsar/ssar - 收集和查看系統(tǒng)運(yùn)行的各種歷史信息, 也提供實(shí)時(shí)模式。

這里舉個(gè)ps的例子, 我們監(jiān)控mysqld服務(wù), 當(dāng)該進(jìn)程使用的內(nèi)存超過系統(tǒng)內(nèi)存70%的時(shí)候, 通過gdb調(diào)用jemalloc的malloc_stats_print函數(shù)來分析可能的內(nèi)存泄漏。

largest=70

while :; do
mem=$(ps -p `pidof mysqld` -o %mem | tail -1)
imem=$(printf %.0f $mem)
if [ $imem -gt $largest ]; then
echo 'p malloc_stats_print(0,0,0)' | gdb --quiet -nx -p `pidof mysqld`
fi
sleep 10
done

perf

perf是性能分析的必備工具, 它最核心的能力是能訪問硬件上的Performance Monitor Unit (PMU), 對分析CPU bound的問題很有幫助, 當(dāng)然perf也支持各種軟件event. perf的主要能力包括

  • 通過采樣發(fā)現(xiàn)程序熱點(diǎn)。
  • 通過硬件PMU深入分析問題的根源, 特別是配合硬件上的優(yōu)化。

perf list可以列出支持的event, 我們可以通過perf來獲取cache misses, cycles等等。

#perf list | grep Hardware
branch-misses [Hardware event]
bus-cycles [Hardware event]
cache-misses [Hardware event]
cache-references [Hardware event]
cpu-cycles OR cycles [Hardware event]
instructions [Hardware event]
L1-dcache-load-misses [Hardware cache event]
L1-dcache-loads [Hardware cache event]
L1-dcache-store-misses [Hardware cache event]
L1-dcache-stores [Hardware cache event]
L1-icache-load-misses [Hardware cache event]
L1-icache-loads [Hardware cache event]
branch-load-misses [Hardware cache event]
branch-loads [Hardware cache event]
dTLB-load-misses [Hardware cache event]
iTLB-load-misses [Hardware cache event]
mem:<addr>[/len][:access] [Hardware breakpoint]

perf使用的時(shí)候一般會傳入以下參數(shù)

  • 通過-e指定感興趣的一個(gè)或多個(gè)event。
  • 指定采樣的范圍, 比如進(jìn)程級別 (-p), 線程級別 (-t), cpu級別 (-C), 系統(tǒng)級別 (-a)

這里使用默認(rèn)的event看下進(jìn)程31925的執(zhí)行情況. 一個(gè)比較重要的信息是insns per cycle (IPC), 也就是每個(gè)cycle能執(zhí)行多少指令, 其他pmu event像cache misses, branch misses如果有問題最終都會反映到IPC上. 雖然沒有一個(gè)明確的標(biāo)準(zhǔn), 但是下面0.09的IPC是比較低的, 有必要繼續(xù)深入。

#perf stat -p 31925  sleep 1

Performance counter stats for process id '31925':

2184.986720 task-clock (msec) # 2.180 CPUs utilized
3,210 context-switches # 0.001 M/sec
345 cpu-migrations # 0.158 K/sec
0 page-faults # 0.000 K/sec
4,311,798,055 cycles # 1.973 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
409,465,681 instructions # 0.09 insns per cycle
<not supported> branches
8,680,257 branch-misses # 0.00% of all branches

1.002506001 seconds time elapsed

除了stat外, perf另一個(gè)可能更常用的方式是采樣來確定程序的熱點(diǎn), 現(xiàn)在有如下程序

void busy(long us) {
struct timeval tv1, tv2;
long delta = 0;
gettimeofday(&tv1, NULL);
do {
gettimeofday(&tv2, NULL);
delta = (tv2.tv_sec - tv1.tv_sec) * 1000000 + tv2.tv_usec - tv1.tv_usec;
} while (delta < us);
}

void A() { busy(2000); }
void B() { busy(8000); }

int main() {
while (1) {
A(); B();
}
return 0;
}

函數(shù)A和B執(zhí)行時(shí)間的比例, perf的采樣結(jié)果和我們期望的2:8基本一致。

#perf record -g -e cycles ./a.out
#perf report
Samples: 27K of event 'cycles', Event count (approx.): 14381317911
Children Self Command Shared Object Symbol
+ 99.99% 0.00% a.out [unknown] [.] 0x0000fffffb925137
+ 99.99% 0.00% a.out a.out [.] _start
+ 99.99% 0.00% a.out libc-2.17.so [.] __libc_start_main
+ 99.99% 0.00% a.out a.out [.] main
+ 99.06% 25.95% a.out a.out [.] busy
+ 79.98% 0.00% a.out a.out [.] B
- 71.31% 71.31% a.out [vdso] [.] __kernel_gettimeofday
__kernel_gettimeofday
- busy
+ 79.84% B
+ 20.16% A
+ 20.01% 0.00% a.out a.out [.] A

strace

trace相對于采樣最大的優(yōu)勢在于精度, trace能抓住每次操作, 這給調(diào)試和理解帶來很大方便. strace專門用來trace系統(tǒng)調(diào)用。

strace通過捕獲所有的系統(tǒng)調(diào)用能快速幫助理解應(yīng)用的某些行為, 這里使用strace來看下上面提到的perf-record的實(shí)現(xiàn), 很容易發(fā)現(xiàn)系統(tǒng)調(diào)用perf_event_open以及它的參數(shù), 因?yàn)橛?28個(gè)cpu, 針對每個(gè)cpu都會調(diào)用一次該系統(tǒng)調(diào)用。

#strace -v perf record -g -e cycles ./a.out
perf_event_open({type=PERF_TYPE_HARDWARE, size=PERF_ATTR_SIZE_VER5, config=PERF_COUNT_HW_CPU_CYCLES, sample_freq=4000, sample_type=PERF_SAMPLE_IP|PERF_SAMPLE_TID|PERF_SAMPLE_TIME|PERF_SAMPLE_CALLCHAIN|PERF_SAMPLE_PERIOD, read_format=0, disabled=1, inherit=1, pinned=0, exclusive=0, exclusive_user=0, exclude_kernel=0, exclude_hv=0, exclude_idle=0, mmap=1, comm=1, freq=1, inherit_stat=0, enable_on_exec=1, task=1, watermark=0, precise_ip=0 /* arbitrary skid */, mmap_data=0, sample_id_all=1, exclude_host=0, exclude_guest=1, exclude_callchain_kernel=0, exclude_callchain_user=0, mmap2=1, comm_exec=1, use_clockid=0, context_switch=0, write_backward=0, namespaces=0, wakeup_events=0, config1=0, config2=0, sample_regs_user=0, sample_regs_intr=0, aux_watermark=0, sample_max_stack=0}, 51876, 25, -1, PERF_FLAG_FD_CLOEXEC) = 30

blktrace

iostat因?yàn)榱6忍钟械臅r(shí)候并不能很好地定位問題, blktrace通過跟蹤每個(gè)I/O, 并在I/O的關(guān)鍵路徑打樁, 可以獲得更精確的信息, 從而幫忙分析問題. blktrace封裝了幾個(gè)命令:

  • blktrace: 收集
  • blkparse: 處理。
  • btt: 強(qiáng)大的分析工具
  • btrace: blktrace/blkparse的一個(gè)簡單封裝, 相當(dāng)于blktrace -d /dev/sda -o - | blkparse -i 。

簡單看下blktrace的輸出, 里面記錄了I/O路徑上的關(guān)鍵信息, 特別地

  • 時(shí)間戳, 性能分析的關(guān)鍵信息之一。
  • event, 第6列, 對應(yīng)到I/O路徑上的關(guān)鍵點(diǎn), 具體對應(yīng)關(guān)系可以查找相應(yīng)手冊或源碼, 理解這些關(guān)鍵點(diǎn)是調(diào)試I/O性能的必要技能。
  • I/O sector. I/O請求對應(yīng)的扇區(qū)和大小。
$ sudo btrace /dev/sda
8,0 0 1 0.000000000 1024 A WS 302266328 + 8 <- (8,5) 79435736
8,0 0 2 0.000001654 1024 Q WS 302266328 + 8 [jbd2/sda5-8]
8,0 0 3 0.000010042 1024 G WS 302266328 + 8 [jbd2/sda5-8]
8,0 0 4 0.000011605 1024 P N [jbd2/sda5-8]
8,0 0 5 0.000014993 1024 I WS 302266328 + 8 [jbd2/sda5-8]
8,0 0 0 0.000018026 0 m N cfq1024SN / insert_request
8,0 0 0 0.000019598 0 m N cfq1024SN / add_to_rr
8,0 0 6 0.000022546 1024 U N [jbd2/sda5-8] 1

這是btt的一個(gè)輸出, 可以看到S2G的個(gè)數(shù)和延遲, 正常情況不應(yīng)該出現(xiàn)這個(gè)問題, 這樣就找到了一條可以深入的線索。

$ sudo blktrace -d /dev/sdb -w 5
$ blkparse sdb -d sdb.bin
$ btt -i sdb.bin
==================== All Devices ====================

ALL MIN AVG MAX N
--------------- ------------- ------------- ------------- -----------

Q2Q 0.000000001 0.000014397 0.008275391 347303
Q2G 0.000000499 0.000071615 0.010518692 347298
S2G 0.000128160 0.002107990 0.010517875 11512
G2I 0.000000600 0.000001570 0.000040010 347298
I2D 0.000000395 0.000000929 0.000003743 347298
D2C 0.000116199 0.000144157 0.008443855 347288
Q2C 0.000118211 0.000218273 0.010678657 347288

==================== Device Overhead ====================

DEV | Q2G G2I Q2M I2D D2C
---------- | --------- --------- --------- --------- ---------
( 8, 16) | 32.8106% 0.7191% 0.0000% 0.4256% 66.0447%
---------- | --------- --------- --------- --------- ---------
Overall | 32.8106% 0.7191% 0.0000% 0.4256% 66.0447%

二、進(jìn)階篇

1.大學(xué)教材

通過教程能夠系統(tǒng)地了解一門課的全貌, 網(wǎng)上搜到的大部分性能分析的教程都是基于Raj Jain的The Art of Computer Systems Performance Analysis, 這本書里面主要包括幾個(gè)部分

  • Part I: AN OVERVIEW OF PERFORMANCE EVALUATION.
  • Part II: MEASUREMENT TECHNIQUES AND TOOLS.
  • Part III: PROBABILITY THEORY AND STATISTICS.
  • Part IV: EXPERIMENTAL DESIGN AND ANALYSIS.
  • Part V: SIMULATION.
  • Part VI: QUEUEING MODELS.

書的重心放在performance analysis上面, 涉及較多概率和統(tǒng)計(jì)的計(jì)算, 另外rice大學(xué)的這個(gè)教程寫得挺不錯(cuò)[1]。

2.技術(shù)博客

  • 參考文末[2]有時(shí)間可以都過一遍, 總的來說主要包括3個(gè)部分

性能分析的方法集. 代表作 USE方法。

性能數(shù)據(jù)的搜集. 代表作 "工具大圖"

性能數(shù)據(jù)的可視化. 代表作 火焰圖。

  • 文末鏈接[3]
  • 文末鏈接[4]
  • 文末鏈接[5]

3.知識結(jié)構(gòu)

系統(tǒng)性能分析在深度和廣度上都有要求, 對底層包括OS和硬件, 以及一些通用能力要做到足夠深, 對上層產(chǎn)品的理解又需要有足夠的廣度, 近一年在混合云親手摸過的產(chǎn)品估計(jì)不下二十款, 當(dāng)然重點(diǎn)分析過的只有幾個(gè)。

操作系統(tǒng)

操作系統(tǒng)是系統(tǒng)分析的基礎(chǔ), 不管是I/O, 內(nèi)存, 網(wǎng)絡(luò), 調(diào)度, docker等等都離不開操作系統(tǒng), 操作系統(tǒng)知識可以從Understanding the Linux Kernel開始, 這本書雖然老了但不妨礙理解OS的基本概念, 慢慢做到能閱讀內(nèi)核文檔和源碼。

在適配某款arm平臺的時(shí)候發(fā)現(xiàn), 在numa off的情況下

  • ecs綁在socket 0上性能好;
  • mysql綁在socket 1上性能好。

能確定的是, 該平臺跨socket性能訪問不管是latency還是throughput和本地訪問都有較大差距, 所以一個(gè)合理的方向是跨socket的內(nèi)存訪問, 如果有類似x86 pcm的話會比較直接, 但是該平臺上缺少該類pmu來查看跨socket的信息, 我們嘗試從OS的角度來回答這個(gè)問題。

首先通過將內(nèi)存壓測工具跑在不同的socket/node上, 發(fā)現(xiàn)numa off表現(xiàn)出了和numa on相同的性能特征, 和硬件產(chǎn)生確認(rèn)該平臺numa off和on的實(shí)現(xiàn)在硬件上并沒有區(qū)別, 只是bios不傳遞numa信息給操作系統(tǒng), 這樣是可以知道物理地址在哪個(gè)socket/node上的。

接下來只要確定ecs/mysql的物理內(nèi)存位置, 就可以用于判斷性能和跨socket的相關(guān)性. Linux在用戶態(tài)可以通過pagemap將虛擬地址對應(yīng)到物理地址, 只需要稍加修改tools/vm/page-types.c就能拿到進(jìn)程對應(yīng)的所有物理地址. 經(jīng)確認(rèn), 確實(shí)ecs/mysql的性能和它們使用的物理內(nèi)存的位置強(qiáng)相關(guān)。

最后要回答的是為什么ecs和mysql表現(xiàn)恰好相反, 注意到ecs使用hugepage而mysql使用normal page, 有如下假設(shè), 具體代碼這里不再列出。

  • 系統(tǒng)啟動(dòng)的時(shí)候, 物理內(nèi)存加到伙伴系統(tǒng)是先socket 0后socket 1。
  • socket 1上的內(nèi)存會被先分出來, 所以mysql分配的內(nèi)存在socket 1. 特定集群的機(jī)器不會隨意跑其他進(jìn)程。
  • 在ecs的host上, 因?yàn)橐峙涞膆ugepage已經(jīng)超過了socket 1上的所有內(nèi)存, 所以后面分配的hugepage已經(jīng)落在了socket 0。
  • hugepage的分配是后進(jìn)先出, 意味著ecs一開始分配到的hugepage在socket 0, 而該機(jī)器資源并沒全部用完, 測試用的幾個(gè)ecs內(nèi)存全落在了socket 0上, 所以將ecs進(jìn)程綁到socket 0的性能更好。

硬件知識

如果一直是x86架構(gòu), 事情會簡單很多, 一是x86的知識大家耳濡目染很久了, 多多少少都了解一些, 二是架構(gòu)變化相對較小, 各種應(yīng)用都適配較好, 需要調(diào)優(yōu)的用例較少. 隨著各種新平臺的崛起, 它們性能各異, 對整個(gè)系統(tǒng)性能帶來的沖擊是巨大的, 這不是影響某個(gè)產(chǎn)品, 這影響的幾乎是所有產(chǎn)品. 最基本地, 我們要處理以下問題

  • 新的平臺上, 應(yīng)用原有的很多假設(shè)被打破, 需要重新適配, 否則性能可能不及預(yù)期. 比如在Intel上面, 開關(guān)numa的性能差距不大,在其他平臺上可能就不一樣
  • 新的平臺要取代老的平臺, 就存在性能的比較. 由于平臺性能差異大并且差異點(diǎn)多,雖然speccpu之類的benchmark能一定程度反應(yīng)平臺整體的計(jì)算性能, 但很多時(shí)候還需要結(jié)合不同場景分別進(jìn)行性能調(diào)優(yōu)。
  • 不排除新平臺存在某種bug或者未知的feature, 都需要我們?nèi)ッ鹘鉀Q的辦法。

數(shù)據(jù)分析

在收集了大量數(shù)據(jù)后, 經(jīng)過數(shù)據(jù)分析可以放大數(shù)據(jù)的價(jià)值

  • 數(shù)據(jù)提取. 利用各種工具比如awk/sed/perl等腳本語言提取所需的數(shù)據(jù)
  • 數(shù)據(jù)抽象. 從不同角度加工數(shù)據(jù), 識別異常, 比如單機(jī)/集群分別是什么表現(xiàn), 統(tǒng)計(jì)哪些值。
  • 可視化. 可視化是數(shù)據(jù)處理非常重要的能力, 一圖勝千言, 火焰圖就是最好的例子. 常用畫圖工具有g(shù)nuplot, excel等。

比如分析MapReduce任務(wù)在10臺機(jī)器的集群上的性能, 即使每臺機(jī)器都體現(xiàn)出一定的共性, 但是如果從集群角度看的話則更加明顯, 也很容易驗(yàn)證這種共性。

換種顯示方式則更加明顯, 很容易知道在不同階段的表現(xiàn), 比如正常Map和Reduce階段cpu利用率也只有80%, 這個(gè)是否符合預(yù)期, 另外在Map和Reduce切換的時(shí)候, 系統(tǒng)idle很明顯, 會不會是潛在優(yōu)化點(diǎn)。

如果有對照的話, 可以直觀地看不到不同表現(xiàn), 特別是巨大的長尾時(shí)間有進(jìn)一步優(yōu)化的空間。

Benchmarking

Benchmarking是獲取性能指標(biāo)最基本的手段, 也是測試常用的方法, 每個(gè)領(lǐng)域幾乎都有自己的一套測試用例. 對于benchmarking, 首先需要知道它測的是什么. 以spec cpu2017為例, 它主要測試的是處理器, 內(nèi)存子系統(tǒng)以及編譯器的性能, 那么在測試的時(shí)候我們除了關(guān)注CPU型號, 還要考慮內(nèi)存大小插法型號, 以及編譯器及其參數(shù)等等, 在做性能比對時(shí)也能清楚它的使用范圍。

Benchmark的一個(gè)特點(diǎn)是可重復(fù)性, spec.org做得很好的一點(diǎn)是上面有大量公布的測試結(jié)果, 可以參考這些測試結(jié)果來驗(yàn)證我們自己的測試方法參數(shù)是否合理. 如果想測試cpu2017, 第一件事就是先重做別人的測試, 直到能復(fù)現(xiàn)別人的數(shù)據(jù), 這個(gè)過程可能會有很多收獲, 對benchmark也會有更多了解. 以intel 8160為例, 在硬件基本一致的情況下, 不經(jīng)額外的配置自己環(huán)境cpu2017 integer rate只能跑到140, 而spec.org上面的測試用例能達(dá)到240, 性能逐步逼近240的過程, 也是深入理解cpu2017的過程。

關(guān)于性能數(shù)據(jù), 首先想要強(qiáng)調(diào)的是有數(shù)據(jù)并不一定比沒數(shù)據(jù)強(qiáng), 只有解釋過的數(shù)據(jù)才是有效數(shù)據(jù), 沒解釋過的數(shù)據(jù)反而會引起不必要的誤判, 比如上面cpu2017的例子, 在做不同平臺性能對比的時(shí)候, 8160到底用140還是240呢, 得出的結(jié)論會十萬八千里. 再比如使用下面的命令測試某新平臺的內(nèi)存延遲

lat_mem_rd -P 1 -N 1 10240 512

測試出的延遲是7.4ns, 不加分析采用該結(jié)果就可能得出新平臺延遲太好的錯(cuò)誤結(jié)論. 所以對待數(shù)據(jù)要足夠謹(jǐn)慎, 一般會有幾個(gè)階段

  • 在信任關(guān)系建立前, 對別人的數(shù)據(jù)保持謹(jǐn)慎. 一是有可能自己對這塊還沒有足夠理解, 二是需要測試報(bào)告提供足夠的信息供他人做判斷。
  • 相信自己的數(shù)據(jù). 必須相信自己, 但是選擇相信自己的數(shù)據(jù), 是因?yàn)橛羞^詳細(xì)合理的分析。
  • 相信別人的數(shù)據(jù). 信任鏈建立之后, 以及自己有了足夠理解后, 選擇相信。

4.更多工具

ftrace

想要快速理解代碼實(shí)現(xiàn), 沒有什么比打印調(diào)用路徑更直接了. ftrace可以用來解決2個(gè)問題

  • 誰調(diào)用了我. 這個(gè)只要在執(zhí)行對應(yīng)函數(shù)的時(shí)候拿到對應(yīng)的棧就可以, 多種工具可以實(shí)現(xiàn);
  • 我調(diào)用了誰. 這個(gè)是ftrace比較unique的功能。

為了方便我們使用ftrace的wrapper trace-cmd, 假設(shè)我們已經(jīng)知道I/O路徑會經(jīng)過generic_make_request, 為了查看完整的路徑我們可以這樣

#trace-cmd record -p function --func-stack -l generic_make_request dd if=/dev/zero of=file bs=4k count=1 oflag=direct

通過report來查看就一目了然了

#trace-cmd report
cpus=128
dd-11344 [104] 4148325.319997: function: generic_make_request
dd-11344 [104] 4148325.320002: kernel_stack: <stack trace>
=> ftrace_graph_call (ffff00000809849c)
=> generic_make_request (ffff000008445b80)
=> submit_bio (ffff000008445f00)
=> __blockdev_direct_IO (ffff00000835a0a8)
=> ext4_direct_IO_write (ffff000001615ff8)
=> ext4_direct_IO (ffff0000016164c4)
=> generic_file_direct_write (ffff00000825c4e0)
=> __generic_file_write_iter (ffff00000825c684)
=> ext4_file_write_iter (ffff0000016013b8)
=> __vfs_write (ffff00000830c308)
=> vfs_write (ffff00000830c564)
=> ksys_write (ffff00000830c884)
=> __arm64_sys_write (ffff00000830c918)
=> el0_svc_common (ffff000008095f38)
=> el0_svc_handler (ffff0000080960b0)
=> el0_svc (ffff000008084088)

現(xiàn)在如果我們想繼續(xù)深入generic_make_request, 使用function_graph plugin

$ sudo trace-cmd record -p function_graph -g generic_make_request dd if=/dev/zero of=file bs=4k count=1 oflag=direct

這樣就可以拿到整個(gè)調(diào)用過程 (report結(jié)果稍微整理過)

$ trace-cmd report
dd-22961 | generic_make_request() {
dd-22961 | generic_make_request_checks() {
dd-22961 0.080 us | _cond_resched();
dd-22961 | create_task_io_context() {
dd-22961 0.485 us | kmem_cache_alloc_node();
dd-22961 0.042 us | _raw_spin_lock();
dd-22961 0.039 us | _raw_spin_unlock();
dd-22961 1.820 us | }
dd-22961 | blk_throtl_bio() {
dd-22961 0.302 us | throtl_update_dispatch_stats();
dd-22961 1.748 us | }
dd-22961 6.110 us | }
dd-22961 | blk_queue_bio() {
dd-22961 0.491 us | blk_queue_split();
dd-22961 0.299 us | blk_queue_bounce();
dd-22961 0.200 us | bio_integrity_enabled();
dd-22961 0.183 us | blk_attempt_plug_merge();
dd-22961 0.042 us | _raw_spin_lock_irq();
dd-22961 | elv_merge() {
dd-22961 0.176 us | elv_rqhash_find.isra.9();
dd-22961 | deadline_merge() {
dd-22961 0.108 us | elv_rb_find();
dd-22961 0.852 us | }
dd-22961 2.229 us | }
dd-22961 | get_request() {
dd-22961 0.130 us | elv_may_queue();
dd-22961 | mempool_alloc() {
dd-22961 0.040 us | _cond_resched();
dd-22961 | mempool_alloc_slab() {
dd-22961 0.395 us | kmem_cache_alloc();
dd-22961 0.744 us | }
dd-22961 1.650 us | }
dd-22961 0.334 us | blk_rq_init();
dd-22961 0.055 us | elv_set_request();
dd-22961 4.565 us | }
dd-22961 | init_request_from_bio() {
dd-22961 | blk_rq_bio_prep() {
dd-22961 | blk_recount_segments() {
dd-22961 0.222 us | __blk_recalc_rq_segments();
dd-22961 0.653 us | }
dd-22961 1.141 us | }
dd-22961 1.620 us | }
dd-22961 | blk_account_io_start() {
dd-22961 0.137 us | disk_map_sector_rcu();
dd-22961 | part_round_stats() {
dd-22961 0.195 us | part_round_stats_single();
dd-22961 0.054 us | part_round_stats_single();
dd-22961 0.955 us | }
dd-22961 2.148 us | }
dd-22961 + 15.847 us | }
dd-22961 + 23.642 us | }

uftrace

uftrace在用戶態(tài)實(shí)現(xiàn)了一個(gè)類似ftrace的功能, 對需要快速理解用戶態(tài)的邏輯會有幫助, 但是需要加上-pg重新編譯源碼, 詳情見[6]。

#gcc -pg a.c
#uftrace ./a.out
# DURATION TID FUNCTION
[ 69439] | main() {
[ 69439] | A() {
0.160 us [ 69439] | busy();
1.080 us [ 69439] | } /* A */
[ 69439] | B() {
0.050 us [ 69439] | busy();
0.240 us [ 69439] | } /* B */
1.720 us [ 69439] | } /* main */

BPF

BPF (eBPF) 是這幾年的熱點(diǎn), 通過BPF幾乎可以看清系統(tǒng)的各個(gè)角落, 給診斷帶來了極大的方便. BPF不是一個(gè)工具, BPF是生產(chǎn)工具的工具, BPF工具編寫是性能分析必須掌握的技能之一。

這里舉個(gè)使用BPF來分析QEMU I/O延遲的例子. 為了簡化問題, 先確保vm里面的塊設(shè)備只有fio在使用, fio控制設(shè)備只有一個(gè)并發(fā)I/O, 這樣我們在host上選擇2個(gè)觀察點(diǎn)

  • tracepoint:kvm:kvm_mmio. host捕獲guest mmio操作, guest里面最終通過寫該mmio發(fā)送請求給host;
  • kprobe:kvm_set_msi. 因?yàn)間uest里面vdb使用msi中斷, 中斷最終通過該函數(shù)注入;

因?yàn)閔ost上有多個(gè)vm和虛擬盤需要區(qū)分, 使用以下信息捕獲并且只捕獲我們關(guān)注的這個(gè)設(shè)備

  • 只關(guān)注該qemu-kvm pid;
  • vbd mmio對應(yīng)的gpa, 這個(gè)可以在guest里面通過lspci獲得;

對于kvm_set_msi, 使用如下信息

  • struct kvm的userspace_pid, struct kvm對應(yīng)的qemu-kvm進(jìn)程;
  • struct kvm_kernel_irq_routing_entry的msi.devid, 對應(yīng)到pci設(shè)備id;
#include <linux/kvm_host.h>

BEGIN {
@qemu_pid = $1;
@mmio_start = 0xa000a00000;
@mmio_end = 0xa000a00000 + 16384;
@devid = 1536;
}

tracepoint:kvm:kvm_mmio /pid == @qemu_pid/ {
if (args->gpa >= @mmio_start && args->gpa < @mmio_end) {
@start = nsecs;
}
}

kprobe:kvm_set_msi {
$e = (struct kvm_kernel_irq_routing_entry *)arg0;
$kvm = (struct kvm *)arg1;
if (@start > 0 && $kvm->userspace_pid == @qemu_pid && $e->msi.devid == @devid) {
@dur = stats(nsecs - @start);
@start = 0;
}
}

interval:s:1 {
print(@dur); clear(@dur);
}

執(zhí)行結(jié)果如下

@dur: count 598, average 1606320, total 960579533

@dur: count 543, average 1785906, total 969747196

@dur: count 644, average 1495419, total 963049914

@dur: count 624, average 1546575, total 965062935

@dur: count 645, average 1495250, total 964436299

5.更深理解

很多技術(shù)需要反復(fù)去理解驗(yàn)證, 每一次可能都有不同的收獲, 這里舉個(gè)loadavg的例子. 引用kernel/sched/loadavg.c最開始的一段注釋

5  * This file contains the magic bits required to compute the global loadavg
6 * figure. Its a silly number but people think its important. We go through
7 * great pains to make it work on big machines and tickless kernels.

這里的silly我想說的是loadavg有一定的局限性, 總的來說loadavg是有一定語義和價(jià)值的, 畢竟它只用了3個(gè)數(shù)字描述了過去一段時(shí)間的"load", 反過來說如果loadavg is silly, 那么有沒有更好的選擇?

  • 如果是實(shí)時(shí)觀察的話, vmstat/dstat輸出的runnable和I/O blocked的信息是種更好的選擇, 因?yàn)橄鄬τ趌oadavg每5秒的采樣。 vmstat可以做到粒度更細(xì), 而且loadavg的算法某種程度可以理解為有損的。
  • 如果是sar/tsar的話, 假設(shè)收集間隔是10min的話, loadavg因?yàn)槟芨采w更大的范圍, 確實(shí)比10min一個(gè)的數(shù)字包含更多的信息。 但我們需要思考它對調(diào)試的真正價(jià)值

另外, 5秒鐘的采樣間隔是比較大的, 我們可以構(gòu)造個(gè)測試用例執(zhí)行了大量時(shí)間但跳過采樣。

  • 獲取load采樣點(diǎn)的時(shí)間。
  • 測試用例剛好跳過該采樣點(diǎn)。

查看calc_load_fold_active在cpu 0上的調(diào)用時(shí)間

kprobe:calc_load_fold_active /cpu == 0/ {
printf("%ld\n", nsecs / 1000000000);
}

運(yùn)行沒有輸出, 監(jiān)控上一層函數(shù)

#include "kernel/sched/sched.h"
kprobe:calc_global_load_tick /cpu == 0/ {
$rq = (struct rq *)arg0;
@[$rq->calc_load_update] = count();
}

interval:s:5 {
print(@); clear(@);
}

執(zhí)行結(jié)果符合預(yù)期

#./calc_load.bt -I /kernel-source
@[4465886482]: 61
@[4465887733]: 1189

@[4465887733]: 62
@[4465888984]: 1188

查看匯編發(fā)現(xiàn)這里代碼被優(yōu)化, 但是剛好id_nr_invalid調(diào)用沒優(yōu)化, 當(dāng)然最方便的是能夠直接在函數(shù)偏移處直接打點(diǎn):

kprobe:id_nr_invalid /cpu == 0/ {
printf("%ld\n", nsecs / 1000000000);
}

根據(jù)這個(gè)時(shí)間戳, 可以很容易跳過load的統(tǒng)計(jì)

while :; do
sec=$(awk -F. '{print $1}' /proc/uptime)
rem=$((sec % 5))
if [ $rem -eq 2 ]; then # 1s after updating load
break;
fi
sleep 0.1
done

for i in {0..63}; do
./busy 3 & # run 3s
done

大量busy進(jìn)程成功跳過load的統(tǒng)計(jì), 可以設(shè)想像cron執(zhí)行的任務(wù)也是有這個(gè)可能的. 雖然不能否認(rèn)loadavg的價(jià)值, 但總的來說load有以下缺陷

  • 系統(tǒng)級別的統(tǒng)計(jì), 和具體應(yīng)用產(chǎn)生的聯(lián)系不夠直接。
  • 使用采樣的方式并且采樣間隔 (5s) 較大, 有的場景不能真實(shí)反映系統(tǒng)。
  • 統(tǒng)計(jì)的間隔較大(1/5/15分鐘), 不利于及時(shí)反映當(dāng)時(shí)的情況。
  • 語義稍微不夠清晰, 不只包括cpu的load, 還包括D狀態(tài)的任務(wù), 這個(gè)本身不是大問題, 更多可以認(rèn)為是feature。

Linux增加了Pressure Stall Information (PSI), PSI從任務(wù)的角度分別統(tǒng)計(jì)了10/60/300s內(nèi)因?yàn)閏pu/io/memory等資源不足而不能運(yùn)行的時(shí)長, 并按照影響范圍分成2類

  • some - 因?yàn)槿鄙儋Y源導(dǎo)致部分任務(wù)不能執(zhí)行。
  • full - 因?yàn)槿鄙儋Y源導(dǎo)致所有任務(wù)不能執(zhí)行, cpu不存在這種情況。

我們在一臺96c的arm機(jī)器上掃描所有cgroup的cpu.pressure

這里會引出幾個(gè)問題, 篇幅原因這里不再展開。

  • 父cgroup的avg為什么比子cgroup還小? 是實(shí)現(xiàn)問題還是有額外的配置參數(shù)?
  • avg10等于33, 也就是1/3的時(shí)間有task因?yàn)闆]有cpu而得不到執(zhí)行, 考慮到系統(tǒng)cpu利用率在40%左右并不算高,。 我們怎么合理看待和使用這個(gè)值:
top - 09:55:41 up 127 days,  1:44,  1 user,  load average: 111.70, 87.08, 79.41
Tasks: 3685 total, 21 running, 2977 sleeping, 1 stopped, 8 zombie
%Cpu(s): 27.3 us, 8.9 sy, 0.0 ni, 59.8 id, 0.1 wa, 0.0 hi, 4.0 si, 0.0 st

6.RTFSC

有的時(shí)候RTFM已經(jīng)不夠了, 手冊包括工具本身的更新沒對上內(nèi)核的節(jié)奏, 我們回到上面頁面回收的例子, 估計(jì)有的同學(xué)之前就有疑問, 沒有scan哪里來的steal。

#sar -B 1

11:00:16 AM pgscank/s pgscand/s pgsteal/s %vmeff
11:00:17 AM 0.00 0.00 3591.00 0.00
11:00:18 AM 0.00 0.00 10313.00 0.00
11:00:19 AM 0.00 0.00 8452.00 0.00

先看sysstat (sar) 里面的實(shí)現(xiàn), 主要是讀取分析/proc/vmstat

  • pgscand: 對應(yīng)到pgscan_direct域。
  • pgscank: 對應(yīng)到pgscan_kswapd域。
  • pgsteal: 對應(yīng)到pgsteal_開頭的域
#gdb --args ./sar -B 1
(gdb) b read_vmstat_paging
(gdb) set follow-fork-mode child
(gdb) r
Breakpoint 1, read_vmstat_paging (st_paging=0x424f40) at rd_stats.c:751
751 if ((fp = fopen(VMSTAT, "r")) == NULL)
(gdb) n
754 st_paging->pgsteal = 0;
(gdb)
757 while (fgets(line, sizeof(line), fp) != NULL) {
(gdb)
759 if (!strncmp(line, "pgpgin ", 7)) {
(gdb)
763 else if (!strncmp(line, "pgpgout ", 8)) {
(gdb)
767 else if (!strncmp(line, "pgfault ", 8)) {
(gdb)
771 else if (!strncmp(line, "pgmajfault ", 11)) {
(gdb)
775 else if (!strncmp(line, "pgfree ", 7)) {
(gdb)
779 else if (!strncmp(line, "pgsteal_", 8)) {
(gdb)
784 else if (!strncmp(line, "pgscan_kswapd", 13)) {
(gdb)
789 else if (!strncmp(line, "pgscan_direct", 13)) {
(gdb)
757 while (fgets(line, sizeof(line), fp) != NULL) {
(gdb)

看下/proc/vmstat都有什么

#grep pgsteal_ /proc/vmstat
pgsteal_kswapd 168563
pgsteal_direct 0
pgsteal_anon 0
pgsteal_file 978205

#grep pgscan_ /proc/vmstat
pgscan_kswapd 204242
pgscan_direct 0
pgscan_direct_throttle 0
pgscan_anon 0
pgscan_file 50583828

最后看看內(nèi)核的實(shí)現(xiàn), pgsteal和pgscan的邏輯是一樣, 除了nr_scanned換成了nr_reclaimed

if (current_is_kswapd()) {
if (!cgroup_reclaim(sc))
__count_vm_events(PGSCAN_KSWAPD, nr_scanned);
count_memcg_events(lruvec_memcg(lruvec), PGSCAN_KSWAPD,
nr_scanned);
} else {
if (!cgroup_reclaim(sc))
__count_vm_events(PGSCAN_DIRECT, nr_scanned);
count_memcg_events(lruvec_memcg(lruvec), PGSCAN_DIRECT,
nr_scanned);
}
__count_vm_events(PGSCAN_ANON + file, nr_scanned);

現(xiàn)在問題很清晰了

  • 這里sar取得是系統(tǒng)的/proc/vmstat, 而cgroup里面pgscan_kswapd和pgscan_direct只會加到cgroup的統(tǒng)計(jì),不會加到系統(tǒng)級的統(tǒng)計(jì)
  • cgroup里面pgsteal_kswapd和pgsteal_direct同樣只會加到cgroup自己的統(tǒng)計(jì)。
  • 但是主要pgscan_anon, pgscan_file和pgsteal_anon, pgsteal_file都只加到系統(tǒng)級的統(tǒng)計(jì)。
  • sar讀取了pgscan_kswapd, pgscan_direct, 以及pgsteal_*, 這里*還包括了pgsteal_anon和pgsteal_file。

這整個(gè)邏輯都亂了, 我們有必要解決這個(gè)bug讓sar的輸出變得更加有意義. 那么在cgroup內(nèi)是不是沒問題?

#df -h .
Filesystem Size Used Avail Use% Mounted on
cgroup 0 0 0 - /sys/fs/cgroup/memory
#grep -c 'pgscan\|pgsteal' memory.stat
0

這些統(tǒng)計(jì)信息在cgroup v1上完全沒有輸出, 而只在v2版本有輸出. 在以前內(nèi)核沒有專門LRU_UNEVICTABLE的時(shí)候, 如果有很多比如mlock page的時(shí)候, 碰到過不停掃描卻不能回收內(nèi)存的情況, 這個(gè)統(tǒng)計(jì)會非常有用, 即使是現(xiàn)在我相信這個(gè)統(tǒng)計(jì)還是有用的, 只是大部分時(shí)候還不用看到這么細(xì)。

7.多上手

紙上得來終覺淺, 自己動(dòng)手去做帶來很多好處

  • 回答預(yù)設(shè)問題. 調(diào)試分析就是不斷提出問題和驗(yàn)證的過程, 沒有上手的話就會一直停留在第一個(gè)問題上. 比如我想了解某平臺上物理內(nèi)存是怎么編址的, 沒有文檔的話只能自己去實(shí)驗(yàn)。
  • 提出新的問題. 調(diào)試分析中不怕有問題, 怕的是提不出問題。
  • 會有意外收獲. 很多時(shí)候并不是有意為之, 比如準(zhǔn)備的是分析cpu調(diào)頻能否降功耗, 上去卻發(fā)現(xiàn)系統(tǒng)一直運(yùn)行在最低頻率。
  • 熟練. 熟練就是效率。
  • 改進(jìn)產(chǎn)品. 可以試想下在整個(gè)云環(huán)境所有機(jī)器上掃描 (類似全面體檢) 會發(fā)現(xiàn)多少潛在問題。

參考資料

[1]https://www.cs.rice.edu/~johnmc/comp528/lecture-notes/

[2]https://brendangregg.com/。

[3]http://dtrace.org/blogs/bmc/

[4]https://blog.stgolabs.net/。

[5]https://lwn.net/。

[6]https://github.com/namhyung/uftrace

[7]https://www.brendangregg.com/

[8]The Art of Computer Systems Performance Analysis。

責(zé)任編輯:武曉燕 來源: 阿里開發(fā)者
相關(guān)推薦

2025-10-17 09:07:39

2023-12-26 08:40:06

分類算法數(shù)據(jù)分析Python

2013-03-06 10:24:12

ksar工具系統(tǒng)性能

2013-03-20 17:18:07

Linux系統(tǒng)性能調(diào)優(yōu)

2021-12-12 18:15:06

Python并發(fā)編程

2010-04-23 11:44:34

Aix系統(tǒng)

2009-09-29 10:39:04

Linuxlinux系統(tǒng)性能檢測

2025-02-11 07:40:27

2020-07-07 10:50:19

Python丄則表達(dá)文本

2024-11-08 14:27:52

系統(tǒng)設(shè)計(jì)數(shù)據(jù)庫

2022-07-15 16:31:49

Postman測試

2024-04-01 08:04:05

JProfilerJVM工具

2011-03-18 11:13:07

LAMP度量性能

2010-04-09 13:26:44

2020-03-02 16:25:03

性能系統(tǒng)軟件

2022-07-26 10:28:00

Linux監(jiān)控命令

2010-05-24 13:29:30

Swap空間

2013-02-28 13:37:59

系統(tǒng)性能調(diào)優(yōu)技術(shù)實(shí)戰(zhàn)

2011-01-05 13:48:55

Linux提高性能

2018-01-22 09:08:14

存儲系統(tǒng)性能帶寬
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

欧美在线视频你懂得| 精品无人码麻豆乱码1区2区 | 成人免费小视频| 91麻豆精品秘密入口| 黄色小说在线观看视频| 在线看成人短视频| 欧美精选一区二区| www.99热这里只有精品| 在线视频三区| 国产91精品一区二区麻豆网站| 欧美一区二区三区免费观看| 黄色片网站在线播放| 欧美男人操女人视频| 欧美麻豆精品久久久久久| 亚洲美免无码中文字幕在线 | 日本一区二区三区高清不卡| 亚洲综合中文字幕在线| 高潮毛片又色又爽免费| 欧美日韩影院| 在线观看成人黄色| 久草福利在线观看| 88xx成人网| 狠狠色狠狠色综合日日小说| 亚洲高清视频一区| 少妇精品视频一区二区| 国产一区二区毛片| 国产精品成人av性教育| 国产精彩视频在线| 亚洲九九视频| 伊人久久久久久久久久| 一起草在线视频| 精品成人18| 欧美无人高清视频在线观看| 欧美 日韩 国产一区| 欧美aaaxxxx做受视频| 亚洲国产精品av| 九九九九九九精品| 亚洲黄色在线观看视频| 精品一区二区影视| 国产成人免费av电影| 日产欧产va高清| 精品91久久久久| 久久99青青精品免费观看| 丁香激情五月少妇| 欧美人与牛zoz0性行为| 精品亚洲一区二区三区在线播放| 深田咏美中文字幕| 欧美专区一区| 日韩欧美一区二区免费| 国产福利精品一区二区三区| 欧美日韩卡一| 欧美亚洲综合另类| 激情五月亚洲色图| 成人精品三级| 欧美夫妻性生活| 69久久久久久| 日韩成人一区| 3751色影院一区二区三区| 性生活免费在线观看| 国产精品久久久久久久久久齐齐 | 欧美电影免费网站| 亚洲国产成人av在线| 黄色性视频网站| 欧美freesex8一10精品| 精品伊人久久97| 欧美老熟妇乱大交xxxxx| 九九视频精品全部免费播放| 亚洲精品一区二区久| 国产精品一二三区在线观看| 欧美美女视频| 久久久www成人免费精品张筱雨 | 亚洲成人在线网站| 免费成人午夜视频| 亚洲欧美在线成人| 91.麻豆视频| 久久久久亚洲AV成人网人人小说| 51精品国产| 国产视频丨精品|在线观看| 91国模少妇一区二区三区| 成人在线电影在线观看视频| 北条麻妃99精品青青久久| 紧身裙女教师波多野结衣| 激情欧美国产欧美| 日产精品久久久一区二区福利| 精品黑人一区二区三区| 蜜桃精品视频在线| 97se国产在线视频| 青青草在线播放| 中文字幕亚洲在| 亚洲中文字幕无码av永久| 巨胸喷奶水www久久久免费动漫| 欧美精品自拍偷拍动漫精品| 稀缺呦国内精品呦| 欧美亚洲国产激情| 久久久久久成人| 国产精品无码一区| 成人激情av网| 亚洲色图自拍| 日韩伦理在线一区| 91 com成人网| 在线免费看黄视频| 激情久久久久| 国产欧美日韩精品在线观看| 欧美 日韩 国产 精品| 欧美韩国日本不卡| 日本a在线免费观看| 男女啪啪999亚洲精品| 亚洲国产小视频在线观看| 少妇无套高潮一二三区| 国产精品激情| 国产精品情侣自拍| 婷婷亚洲一区二区三区| 自拍偷拍亚洲欧美日韩| 男人天堂1024| 日韩中文在线| 中文字幕欧美日韩| 毛片毛片女人毛片毛片| 国产成人精品亚洲777人妖| 神马欧美一区二区| 日本蜜桃在线观看视频| 日韩欧美国产一区二区在线播放 | 蜜桃精品噜噜噜成人av| 欧美成年人视频网站| 国产伦理一区二区三区| 国产www视频| 国产精品视频线看| 国产肥臀一区二区福利视频| 日韩精品视频中文字幕| 在线精品国产欧美| 国产熟妇一区二区三区四区| 99久久99久久免费精品蜜臀| 永久免费看av| а天堂中文最新一区二区三区| 国产丝袜一区视频在线观看| 国产无遮挡裸体免费视频| 国产美女视频91| 五月婷婷综合色| 男人最爱成人网| 亚洲精品中文字幕女同| 国产成人愉拍精品久久| 不卡av免费在线观看| 黄网站色视频免费观看| 国产精品一区免费在线| 菠萝蜜影院一区二区免费| 波多野结衣视频观看| 97成人超碰视| 国产91在线免费| 欧美日韩麻豆| 欧美一区第一页| 麻豆国产在线播放| 日韩欧美一区二区在线| 西西大胆午夜视频| 免费看黄裸体一级大秀欧美| 欧美午夜精品久久久久免费视| 精品捆绑调教一区二区三区| 亚洲精品一线二线三线无人区| 久久激情免费视频| 成人激情免费网站| 国产不卡一区二区视频| 日韩av三区| 日本欧美一二三区| 九色视频在线观看免费播放| 91黄视频在线| 日本视频在线免费| 韩国女主播成人在线观看| 国产高清免费在线| 亚洲一区电影| 久久久久久无码午夜精品直播| www..com.cn蕾丝视频在线观看免费版 | 国产日产欧产精品推荐色| 久久91亚洲精品中文字幕| 亚洲视频欧美视频| 午夜精品福利视频| 日韩在线免费高清视频| 夜夜嗨av一区二区三区四区| 一区二区三区国产在线观看| 亚洲天堂av综合网| 在线观看欧美日韩国产| 色妞色视频一区二区三区四区| 日本电影亚洲天堂| 秋霞欧美一区二区三区视频免费| 激情综合网激情| 97中文字幕在线| 香蕉久久夜色精品国产使用方法 | 夜鲁夜鲁夜鲁视频在线播放| 亚洲日本中文字幕| 国产伦一区二区| 午夜精品爽啪视频| 久久久久亚洲AV成人无在| 国产一区二区福利视频| 美女日批免费视频| 日韩电影一区| 国产亚洲情侣一区二区无| 欧美韩国亚洲| 久久999免费视频| 欧美老女人性开放| 欧美人与z0zoxxxx视频| 国产无套内射又大又猛又粗又爽| 国产欧美日韩另类视频免费观看| 美女被艹视频网站| 久久午夜视频| 久久久久久久香蕉| 精品国产一区二区三区香蕉沈先生| 91久久久精品| 在线最新版中文在线| 欧美成人精品在线视频| 六十路在线观看| 欧美大片拔萝卜| 欧美男人天堂网| 无码av免费一区二区三区试看| 谁有免费的黄色网址| 成人亚洲精品久久久久软件| 国产福利影院在线观看| 亚洲精品资源| 糖心vlog在线免费观看| 日韩中文在线电影| 蜜桃av久久久亚洲精品| 亚洲三级av| 成人激情综合网| 日本欧美日韩| 欧美孕妇性xx| а√天堂8资源中文在线| 久久午夜a级毛片| av男人的天堂在线| 亚洲欧美一区二区三区四区| 狠狠躁日日躁夜夜躁av| 91精品国产一区二区人妖| 九九热最新视频| 日韩欧美在线视频免费观看| 国产中文字幕免费| 亚洲黄一区二区三区| 人人干在线观看| 美女网站视频在线| 精品剧情v国产在线观看在线| 国产一区二区女内射| 欧美亚洲一区二区在线| 99超碰在线观看| 欧美性精品220| 男人午夜免费视频| 黑人巨大精品欧美一区免费视频 | 日韩欧美综合在线视频| 免费在线观看黄网站| 亚洲综合色噜噜狠狠| 亚洲欧美一区二区三区四区五区| 最近中文字幕一区二区三区| 天堂av网手机版| 国产精品美女久久久久久久 | 欧美少妇性xxxx| 日本精品一区| 成人午夜国产| 亚洲欧美一区二区原创| 精品一区二区三区在线| 日韩欧美一区二区三区四区| 精品久久视频| 神马影院一区二区| 成人婷婷网色偷偷亚洲男人的天堂| 日韩美女一区| 日韩精品不卡一区二区| 一级二级三级欧美| 亚洲国产精品成人| 国产精品videossex国产高清 | 久久久久久久久久福利| 天使萌一区二区三区免费观看| 欧美日韩第二页| 日本中文一区二区三区| 久久久久久久久久久久91| 美女久久久精品| 午夜xxxxx| 成人精品亚洲人成在线| 国产精品无码在线| 久久精品水蜜桃av综合天堂| 山东少妇露脸刺激对白在线| 一区免费观看视频| 国产在线精品观看| 91精品福利视频| 国产精品国产三级国产普通话对白| 69久久99精品久久久久婷婷| www.蜜臀av.com| 亚洲精品久久久久国产| 国产精品免费播放| 欧美精品在线视频观看| 成人免费网站观看| 国产精品美女网站| 日韩一级淫片| 美日韩免费视频| 围产精品久久久久久久| 鲁一鲁一鲁一鲁一色| 青草国产精品久久久久久| 欧美色图校园春色| 91日韩精品一区| 制服丨自拍丨欧美丨动漫丨| 亚洲在线中文字幕| 亚洲成人av网址| 亚洲精品一区二区三区香蕉| 国产精品久久久久一区二区国产| 另类美女黄大片| 超碰超碰人人人人精品| 91中文字幕在线观看| 青青草原在线亚洲| 最新av在线免费观看| 午夜一级久久| 91丨porny丨九色| 国产嫩草影院久久久久| 国产极品在线播放| 欧美日韩一区中文字幕| 无码精品视频一区二区三区| 日韩中文字幕av| 欧美少妇精品| 91老司机在线| 欧美日韩一区二区三区视频播放| 欧美极品少妇无套实战| 蜜臀a∨国产成人精品| 亚洲午夜久久久久久久久红桃| 亚洲欧美日韩精品久久久久| 精品视频一二三区| 亚洲大胆人体视频| 国产高清一区二区三区视频 | 亚洲精品高潮| 亚洲精品中字| 日韩精品亚洲一区| 日韩精品一区二区三区高清免费| 亚洲男人的天堂网| 亚洲自拍第二页| 亚洲视频视频在线| 牛牛精品一区二区| 国产传媒欧美日韩| 欧美在线1区| 亚洲一区二区福利视频| 欧美国产精品一区| 亚洲综合久久网| 日韩精品一区二区视频| xxx在线免费观看| 超碰97在线人人| 亚洲一级淫片| 亚洲天堂国产视频| 亚洲欧洲美洲综合色网| 日韩免费av网站| 亚洲图片在线综合| 日韩毛片免费观看| 日本在线观看一区二区三区| 亚洲免费影院| 国产精品第七页| 精品久久久精品| 天堂中文字幕在线| 欧美综合激情网| 亚洲aaa级| 凹凸日日摸日日碰夜夜爽1| 91美女在线视频| 五月婷婷色丁香| 国产亚洲精品成人av久久ww| gogo亚洲高清大胆美女人体| 免费国产一区二区| 久久久夜夜夜| 一级黄色毛毛片| 欧美久久一二区| 亚洲综合图区| 国产自产在线视频一区| 一级成人国产| 伊人网伊人影院| 欧美日韩久久一区二区| 国产精品剧情| 国产精品一区二区不卡视频| 亚洲激情av| 三级网站在线免费观看| 欧美色偷偷大香| 麻豆av在线导航| 国产精品yjizz| 国产日韩免费| 91社区视频在线观看| 91精选在线观看| а√在线中文网新版地址在线| 久久精品一区二区三区不卡免费视频 | 97久久精品一区二区三区的观看方式| 五月天男人天堂| 高清不卡一区二区在线| 国产美女激情视频| 日韩在线欧美在线| 国产成人一二片| 国产真人无码作爱视频免费| 日韩一区欧美一区| 天天干天天做天天操| 国产精品成人v| 欧美亚韩一区| 日韩乱码人妻无码中文字幕久久| 欧美日韩一区小说| 青春草免费在线视频| 免费看成人午夜电影| 狠狠色丁香九九婷婷综合五月| 国产精品第108页| 伊人成人开心激情综合网| 午夜久久av| 91淫黄看大片| 亚洲成人免费影院| wwwww在线观看免费视频| 91成人在线看| 蜜桃久久久久久久| 日韩精品视频免费看| 中文字幕日韩有码| 猫咪成人在线观看| 中文字幕12页|