天天看點

Linux 性能診斷 perf使用指南

linux , perf , 性能診斷 , stap , systemtap , strace , dtrace , dwarf , profiler , perf_events

linux在服務端已占據非常大的比例,很多業務很多服務都跑在linux上面。

軟體運作在linux下,軟體本身、以及linux系統的性能診斷也成為熱門的話題。

例如,你要如何回答這些問題

又或者你是一名dba或者開發人員,想知道資料庫在跑某些benchmark時,性能瓶頸在哪裡,是io,是等待,還是網絡,代碼瓶頸在哪裡?

在linux下診斷的工具比較多,比如systemtap, dtrace, perf。

本文将介紹一下perf的用法,網上很多叫法如perf_events , perf profiler , performance counters for linux。叫法不同,都指perf。

perf是linux 2.6+核心中的一個工具,在核心源碼包中的位置 tools/perf。

perf利用linux的trace特性,可以用于實時跟蹤,統計event計數(perf stat);或者使用采樣(perf record),報告(perf report|script|annotate)的使用方式進行診斷。

perf指令行接口并不能利用所有的linux trace特性,有些trace需要通過ftrace接口得到。

Linux 性能診斷 perf使用指南

這張圖大緻列出了perf支援的跟蹤事件,從kernerl到user space,支援塊裝置、網絡、cpu、檔案系統、記憶體等,同時還支援系統調用,使用者庫的事件跟蹤。

你可以使用perf list輸出目前核心perf 支援的預置events

我們看到perf支援這麼多的事件和trace,它依賴了很多的接口來幹這件事情。

1. symbols

沒有符号表,無法将記憶體位址翻譯成函數和變量名。

例如,無符号表的跟蹤顯示如下

有符号表的跟蹤顯示如下

如何安裝符号表?

對于核心代碼的符号表,在編譯核心時,使用config_kallsyms=y。 檢查如下

對于使用者安裝軟體的符号表,如果是yum安裝的,可以安裝對應的debuginfo包。

如果是使用者自己編譯的,例如使用gcc編譯時加上-g選項。

2. perf annotate

perf annotate can generate sourcecode level information if the application is compiled with -ggdb.

3. stack traces (使用perf record -g收集stack traces)

要跟蹤完整的stack,編譯時需要注意幾個東西。

3.1 編譯perf時包含libunwind和-g dwarf,需要3.9以上的核心版本。

3.2 有些編譯優化項會忽略frame pointer,是以編譯軟體時必須指定 -fno-omit-frame-pointer ,才能跟蹤完整的stack trace.

3.3 編譯核心時包含 config_frame_pointer=y

總結一下,要愉快的跟蹤更完備的資訊,就要在編譯軟體時打開符号表的支援(gcc -g),開啟annotate的支援(gcc -ggdb),以及stack trace的支援(gcc -fno-omit-frame-pointer)。

了解了perf event後,我們可以更精細的,有針對性的對事件進行跟蹤,采樣,報告。

當然,你也可以不指定事件,全面采樣。

例如centos你可以使用yum安裝,也可以使用源碼安裝。

perf在核心源碼的tools/perf中,是以下載下傳與你的核心大版本一緻的核心源碼即可

安裝依賴庫,有一個小竅門可以找到依賴的庫

通常依賴 gcc make bison flex elfutils libelf-dev libdw-dev libaudit-dev python-dev binutils-dev

并不是每個開關都需要,但是有些沒有就不友善或者功能缺失,例如沒有打開符号表的話,看到的是一堆記憶體位址。

一些開關的用途介紹

1. kernel-level symbols are in the kernel debuginfo package, or when the kernel is compiled with config_kallsyms.

2. the kernel stack traces are incomplete. now a similar profile with config_frame_pointer=y

3. 當我們使用perf record [stack traces (-g)]時,可以跟蹤stack,但是如果核心編譯時沒有指定config_frame_pointer=y,perf report時就會看到缺失的資訊。

不包含config_frame_pointer=y時

包含config_frame_pointer=y時 (much better -- the entire path from the write() syscall (__write_nocancel) to iowrite16() can be seen.)

4. 如果要使用動态跟蹤,即跟蹤任意指定代碼,則需要打開這些開關:

for kernel analysis, using config_kprobes=y and config_kprobe_events=y, to enable kernel dynamic tracing. and config_frame_pointer=y, for frame pointer-based kernel stacks.

for user-level analysis, config_uprobes=y and config_uprobe_events=y, for user-level dynamic tracing.

5. 如果打開了config_debug_info,則可以在動态跟蹤中列印核心變量的值。

if your kernel has debuginfo (config_debug_info=y), you can fish out kernel variables from functions. this is a simple example of examining a size_t (integer)

例如

通過以下指令可以檢視linux的config

先了解一下概貌

perf 指令用法還是挺簡單的,根據功能區分了command,每個command有各自的用法。

用得比較多的有list, record, report, script, stat, top。

要得到每個command的用法也蠻簡單,可以使用perf help command得到。

跟蹤時可以指定事件,cpu,以及是否跟蹤stack trace。

輸出如下

輸入 ? 可以得到top的幫助介紹

輸入e全部展開,展開後可以得到stack trace的結果, 如果發現有位址的資訊,但是沒有符号表的資訊,可能是軟體編譯時沒有指定-g,如果stack資訊不完整,則軟體編譯時需要加-fno-omit-frame-pointer(參考前面章節的介紹)。

輸入c全部收起

symbol列[]中字元代表的含義如下,通常是k或者.表示kernel和user space事件。

perf record用來收集統計資訊,通常的用法包括

1. 使用record收集統計資訊,可以收集全局的,指定pid或者線程id的,指定cpu的,指定user id的。

2. 收集間隔,可以指定采樣的頻率,采樣的event數,采樣時間。

3. 采集的詳細程度,可以指定event,使用cpu實時排程政策的程序(可以參考rhel 講cgroup cpu部分的文章),是否跟蹤stack chain,

例子

解讀前面收集到的perf.data.

常用的開關如下,--tui是互動式的文本顯示視窗,--stdio是文本顯示視窗。

互動式顯示例子,看概貌挺友善的 (常用的互動指令: e擴充,c收斂,q退出)

文本顯示例子,看細節挺友善

首先顯示了一些異常,如果你發現少了符号表或者什麼的,可以根據提示安裝debuginfo,或者重新編譯核心或軟體。

報告的細節如下

一條條列印perf.data内的資料,輸出的是perf record收集到的原始資料。

生成熱力圖、火焰圖也需要perf script的輸出,從最原始的資訊中提取資料,生成svg。

解讀前面收集到的perf.data,輔以彙編指令顯示。

用來測試系統的一些常見名額的性能(如ipc, message or pipe, memcpy)。

測試程序或線程通信性能

從測試來看,線程, pipe()通信效率是最高的。

測試pipe()

測試所有,包括memcpy

perf 除了可以采樣(使用perf record)(包括call stack trace),還可以用于event計數。

perf stat就是用于event計數的,可以跟蹤指定指令的event計數。

如果你想跟蹤postgresql資料庫,可以把資料庫的所有程序塞到cgroup裡,然後使用perf stat -g cgname統計整個cgroup。

perf stat還支援-e指定事件,事件支援通配符。

使用instruction:modifier可以指定要跟蹤的instruction在哪裡?在kernel space或user space,又或者在虛拟機,虛拟機os,主控端os等。

modifier用法如下,寫在event:後面。

modifiers

description

example

u

monitor at priv level 3, 2, 1 (user)

event:u

k

monitor at priv level 0 (kernel)

event:k

h

monitor hypervisor events on a virtualization environment

event:h

monitor host machine on a virtualization environment

g

monitor guest machine on a virtualization environment

event:g

例子 -e instructions:u

perf probe可以實作動态跟蹤,指哪打哪。靜态跟蹤是預置的,而動态跟蹤是補充預置不足的。

Linux 性能診斷 perf使用指南

比如你想跟蹤kernel的某個function, 甚至某一行代碼,某些變量的值。

或者你想跟蹤使用者軟體的某個function,甚至某一行代碼,某些變量的值。

首先要添加需要動态跟蹤的對象(function, var, ...)

然後record,和report分析,這和前面的用法是一樣的。

跟蹤某行代碼

跟蹤使用者軟體的指定function

event中的一種類型,實際上是一些比較常見的系統調用。

不在裡面的可以使用前面介紹的動态跟蹤的方式進行跟蹤。

支援哪些tracepoint

主要包含以下tracepoint subtype

使用perf report -tui或者-stdio輸出的文本不夠直覺的話,使用火焰圖可以很直覺的表現出哪些代碼是瓶頸所在。

生成火焰圖

Linux 性能診斷 perf使用指南

生成熱力圖

Linux 性能診斷 perf使用指南

要完備的跟蹤和列印跟蹤(符号表、call stack trace、彙編指令)資訊,建議核心編譯時加上

編譯perf時需要支援libunwind, 并加上

軟體編譯時加上

如果是yum安裝的軟體,可以安裝對應的debuginfo包。

5. 火焰圖

<a href="https://github.com/brendangregg/flamegraph">https://github.com/brendangregg/flamegraph</a>

6. 熱力圖

<a href="https://github.com/brendangregg/heatmap">https://github.com/brendangregg/heatmap</a>