Linux內(nèi)核性能調(diào)試工具之ftrace

一、ftrace介紹

本文基于Rockpi 4A單板Linux 4.4內(nèi)核介紹ftrace的使用方法,其它內(nèi)核版本的ftrace使用方法類似。

ftrace(Function Tracer)是直接內(nèi)置在Linux內(nèi)核的跟蹤程序,作為一個(gè)內(nèi)部的tracer提供給系統(tǒng)的開發(fā)者和設(shè)計(jì)者,幫他們弄清內(nèi)核正在發(fā)生的行為,用于調(diào)試或分析用戶空間之外的延遲和性能問題。

ftrace是內(nèi)核態(tài)的strace,用于追蹤內(nèi)核態(tài)的調(diào)用記錄,功能比strace強(qiáng)大。ftrace最開始是一個(gè)函數(shù)跟蹤器,主要用于記錄內(nèi)核函數(shù)的運(yùn)行軌跡。隨著功能的增加,演變成一個(gè)跟蹤框架,包括:用延遲跟蹤來檢查中斷禁用和啟用之間發(fā)生的情況、搶占和從任務(wù)被喚醒到任務(wù)實(shí)際調(diào)度的時(shí)間。

整個(gè)ftrace框架可以分為幾部分:ftrace核心框架,RingBufferdebugfs,Tracepoint和各種Tracer。見下圖:

image.png

二、ftrace內(nèi)核配置

1、內(nèi)核配置

ftrace Linux內(nèi)核驅(qū)動(dòng)配置方法如下:

使用make ARCH=arm64 menuconfig命令,進(jìn)入如下配置界面:

image.png

選擇Kernel hacking -> Tracers,進(jìn)入如下配置界面:
image.png

Branch Profiling (Trace likely/unlikely profiler)中,可以選擇相關(guān)的Branch Profiling,配置如下:
image.png

ftrace內(nèi)核代碼路徑:kernel/trace/,相關(guān)驅(qū)動(dòng)文件如下:

root@ubuntu:/home/run/code/rockchip-bsp/kernel/kernel/trace# ls *.c
blktrace.c    power-traces.c           trace_benchmark.c  trace_event_perf.c      trace_export.c           trace_kdb.c        trace_output.c        trace_sched_wakeup.c      trace_stack.c
bpf_trace.c   ring_buffer_benchmark.c  trace_branch.c     trace_events.c          trace_functions.c        trace_kprobe.c     trace_printk.c        trace_selftest.c          trace_stat.c
ftrace.c      ring_buffer.c            trace.c            trace_events_filter.c   trace_functions_graph.c  trace_mmiotrace.c  trace_probe.c         trace_selftest_dynamic.c  trace_syscalls.c
gpu-traces.c  rpm-traces.c             trace_clock.c      trace_events_trigger.c  trace_irqsoff.c          trace_nop.c        trace_sched_switch.c  trace_seq.c               trace_uprobe.c

2、ftrace路徑

單板系統(tǒng)啟動(dòng)后,ftrace 通過 debugfs向用戶態(tài)提供訪問接口。相關(guān)接口如下:

root@xiaotianbsp:/sys/kernel/debug/tracing# ls
README                      options              stack_max_size
available_events            per_cpu              stack_trace
available_filter_functions  printk_formats       stack_trace_filter
available_tracers           saved_cmdlines       trace
buffer_size_kb              saved_cmdlines_size  trace_clock
buffer_total_size_kb        saved_tgids          trace_marker
current_tracer              set_event            trace_options
dyn_ftrace_total_info       set_event_pid        trace_pipe
enabled_functions           set_ftrace_filter    trace_stat
events                      set_ftrace_notrace   tracing_cpumask
free_buffer                 set_ftrace_pid       tracing_max_latency
function_profile_enabled    set_graph_function   tracing_on
instances                   set_graph_notrace    tracing_thresh
max_graph_depth             snapshot

ftrace部分節(jié)點(diǎn)含義如下:

1)available_filter_functions

可跟蹤的所有函數(shù)列表,不在其中的函數(shù)無法跟蹤。

2)available_tracers

可用跟蹤器。

3)current_tracer

當(dāng)前使用的跟蹤器。

4)function_profile_enabled

函數(shù)性能分析器,打開后,trace_stat/目錄下會(huì)顯示function的統(tǒng)計(jì)信息。

5)max_graph_depth

顯示函數(shù)最大調(diào)用深度,在后續(xù)實(shí)例中解釋。

6)set_ftrace_filter

設(shè)置跟蹤的函數(shù)列表,支持批量設(shè)置,如*ios。

7)set_ftrace_notrace

設(shè)置不跟蹤的函數(shù)列表。

8)set_ftrace_pid

設(shè)置跟蹤進(jìn)程的pid,可查看用戶空間接口使用內(nèi)核的函數(shù)調(diào)用關(guān)系。

9)trace

跟蹤的輸出(Ring buffer)。

10)trace_pipe

跟蹤的輸出,提供持續(xù)不斷的數(shù)據(jù)流(實(shí)時(shí)輸出)。

11)trace_stat/

函數(shù)性能分析的輸出目錄。

12)tracing_on

控制trace打開和關(guān)閉。

上面節(jié)點(diǎn)介紹也可通過README查看

root@linaro-alip:/sys/kernel/debug/tracing# cat README
tracing mini-HOWTO:

# echo 0 > tracing_on : quick way to disable tracing
# echo 1 > tracing_on : quick way to re-enable tracing

 Important files:
  trace                 - The static contents of the buffer
                          To clear the buffer write into this file: echo > trace
  trace_pipe            - A consuming read to see the contents of the buffer
  current_tracer        - function and latency tracers
  available_tracers     - list of configured tracers for current_tracer
  buffer_size_kb        - view and modify size of per cpu buffer
  buffer_total_size_kb  - view total size of all cpu buffers

  trace_clock           -change the clock used to order events
       local:   Per cpu clock but may not be synced across CPUs
      global:   Synced across CPUs but slows tracing down.
     counter:   Not a clock, but just an increment
      uptime:   Jiffy counter from time of boot
        perf:   Same clock that perf events use
        ...

README對應(yīng)驅(qū)動(dòng)文件:kernel/trace/trace.c

static const char readme_msg[] =
        "tracing mini-HOWTO:\n\n"
        "# echo 0 > tracing_on : quick way to disable tracing\n"
        "# echo 1 > tracing_on : quick way to re-enable tracing\n\n"
        " Important files:\n"
        "  trace\t\t\t- The static contents of the buffer\n"
        "\t\t\t  To clear the buffer write into this file: echo > trace\n"
        "  trace_pipe\t\t- A consuming read to see the contents of the buffer\n"
        "  current_tracer\t- function and latency tracers\n"
        "  available_tracers\t- list of configured tracers for current_tracer\n"
        "  buffer_size_kb\t- view and modify size of per cpu buffer\n"
        "  buffer_total_size_kb  - view total size of all cpu buffers\n\n"
        "  trace_clock\t\t-change the clock used to order events\n"
        "       local:   Per cpu clock but may not be synced across CPUs\n"
        "      global:   Synced across CPUs but slows tracing down.\n"
        "     counter:   Not a clock, but just an increment\n"
        "      uptime:   Jiffy counter from time of boot\n"
        "        perf:   Same clock that perf events use\n"
        ....

三、ftrace種類

通過下面的命令可以查看目前系統(tǒng)可用的tracer和目前使用的tracer。

root@xiaotianbsp:/# cd /sys/kernel/debug/tracing/
root@xiaotianbsp:/sys/kernel/debug/tracing# cat available_tracers
blk branch function_graph wakeup_dl wakeup_rt wakeup irqsoff function nop
root@xiaotianbsp:/sys/kernel/debug/tracing# cat current_tracer
nop

tracer有很多類型,主要包括幾大類:

1、函數(shù)類

1)function

表示函數(shù)被調(diào)用的流程,類似Linux內(nèi)核的dump_stack()函數(shù)功能,需要配置調(diào)用棧(options/func_stack_trace)。

2)function_graph

表示本函數(shù)內(nèi)部的調(diào)用實(shí)現(xiàn)。

2、延時(shí)類

1)irqsoff

當(dāng)中斷被禁止時(shí),系統(tǒng)無法響應(yīng)外部事件。此時(shí),時(shí)鐘也無法產(chǎn)生tick中斷,意味著系統(tǒng)響應(yīng)延遲。irqsoff tracer能夠跟蹤并記錄內(nèi)核中哪些函數(shù)禁止了中斷,對于對于中斷禁止事件最長的,irqsoff將在tracer文件的第一行標(biāo)出,方便迅速定位造成響應(yīng)延遲的罪魁禍?zhǔn)住?/p>

2)wakeup_rt

跟蹤RT類型的任務(wù)從獲得調(diào)度到被喚醒的最長延遲時(shí)間。

3)wakeup

跟蹤普通優(yōu)先級(jí)進(jìn)程的調(diào)度延遲,即高優(yōu)先級(jí)進(jìn)程從進(jìn)入ready狀態(tài)到獲得CPU的延遲時(shí)間。該tracer只針對實(shí)時(shí)進(jìn)程。

4)preemptoff

跟蹤并記錄禁止內(nèi)核搶占的函數(shù),并清晰地顯示出禁止搶占時(shí)間最長的內(nèi)核函數(shù)。

5)preemptirqsoff

跟蹤和記錄禁止中斷或禁止搶占的內(nèi)核函數(shù),以及禁止時(shí)間最長的函數(shù)。

3、其他類

1)blk

跟蹤塊設(shè)備函數(shù)。

2)branch

跟蹤內(nèi)核程序中的likelyunlikely分支預(yù)測命中率情況。branch tracer能夠記錄這些分支語句有多少次預(yù)測成功,從而優(yōu)化程序提供線索。

3)nop

不跟蹤任務(wù)內(nèi)核活動(dòng)。將nop寫入current_tracer文件可刪除之前所用的跟蹤器,并清空之前收集到的跟蹤信息。

ftrace可用來排查下面問題:

1)特定內(nèi)核函數(shù)調(diào)用的頻次(function)。

2)內(nèi)核函數(shù)在被調(diào)用的過程中路徑(調(diào)用棧)(function+stack)。

3)內(nèi)核函數(shù)調(diào)用的子函數(shù)流程(function graph)。

4)由于搶占導(dǎo)致的高延時(shí)路徑等。

四、ftrace使用方法

ftrace使用方法概括如下:

1)關(guān)閉并配置tracer類型

2)配置tracer參數(shù)

3)打開并查看tracer內(nèi)容

1、function

下面介紹如何配置跟蹤function功能。

root@xiaotianbsp:~#cd /sys/kernel/debug/tracing/

## 1、配置tracer類型
root@xiaotianbsp:/sys/kernel/debug/tracing# echo 0 > tracing_on
root@xiaotianbsp:/sys/kernel/debug/tracing# cat available_tracers
blk branch function_graph wakeup_dl wakeup_rt wakeup irqsoff function nop
root@xiaotianbsp:/sys/kernel/debug/tracing# echo function > current_tracer

## 2、設(shè)置tracer參數(shù)
# 跟蹤blk_start_request函數(shù)
root@xiaotianbsp:/sys/kernel/debug/tracing# echo blk_start_request > set_ftrace_filter
root@xiaotianbsp:/sys/kernel/debug/tracing# echo > trace   ## 清ringbuffer

## 3、查看trace
root@xiaotianbsp:/sys/kernel/debug/tracing# cat trace
# tracer: function
#
# entries-in-buffer/entries-written: 0/0   #P:6
#
#                              _-----=> irqs-off
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
root@xiaotianbsp:/sys/kernel/debug/tracing# echo 1 > tracing_on
root@xiaotianbsp:/sys/kernel/debug/tracing# cat trace
# tracer: function
#
# entries-in-buffer/entries-written: 0/0   #P:6
#
#                              _-----=> irqs-off
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
root@linaro-alip:/sys/kernel/debug/tracing# cat trace
# tracer: function
#
# entries-in-buffer/entries-written: 5/5   #P:6
#
#                              _-----=> irqs-off
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
         mmcqd/0-157   [004] d...   406.503900: blk_start_request <-blk_fetch_request
         mmcqd/0-157   [004] d...   406.504015: blk_start_request <-blk_fetch_request
         mmcqd/0-157   [004] d...   406.515351: blk_start_request <-blk_fetch_request
         mmcqd/0-157   [004] d...   406.549479: blk_start_request <-blk_fetch_request
         mmcqd/0-157   [004] d...   406.599922: blk_start_request <-blk_fetch_request

如果想查看函數(shù)調(diào)用棧,可增加如下配置:

root@linaro-alip:/sys/kernel/debug/tracing# echo 0 > tracing_on
root@linaro-alip:/sys/kernel/debug/tracing# echo > trace
# 配置函數(shù)棧跟蹤
root@linaro-alip:/sys/kernel/debug/tracing# echo 1 > options/func_stack_trace
root@linaro-alip:/sys/kernel/debug/tracing# echo 1 > tracing_on
root@linaro-alip:/sys/kernel/debug/tracing# cat trace
# tracer: function
#
# entries-in-buffer/entries-written: 4/4   #P:6
#
#                              _-----=> irqs-off
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
         mmcqd/0-157   [004] d...   232.540969: blk_start_request <-blk_fetch_request
         mmcqd/0-157   [004] d...   232.540978: <stack trace>  ## 顯示函數(shù)調(diào)用棧
 => ftrace_ops_no_ops
 => ftrace_graph_call
 => blk_start_request
 => blk_fetch_request
 => mmc_queue_thread
 => kthread
 => ret_from_fork
         mmcqd/0-157   [004] d...   232.553196: blk_start_request <-blk_fetch_request
         mmcqd/0-157   [004] d...   232.553202: <stack trace>
 => ftrace_ops_no_ops
 => ftrace_graph_call
 => blk_start_request
 => blk_fetch_request
 => mmc_queue_thread
 => kthread
 => ret_from_fork

2、function_graph

下面介紹如何配置跟蹤function_graph功能。

root@xiaotianbsp:~#cd /sys/kernel/debug/tracing/

## 1、配置tracer類型
root@xiaotianbsp:/sys/kernel/debug/tracing# echo 0 > tracing_on
root@xiaotianbsp:/sys/kernel/debug/tracing# cat available_tracers
blk branch function_graph wakeup_dl wakeup_rt wakeup irqsoff function nop
root@xiaotianbsp:/sys/kernel/debug/tracing# echo function_graph > current_tracer

## 2、設(shè)置tracer參數(shù)
root@xiaotianbsp:/sys/kernel/debug/tracing# echo blk_start_request > set_graph_function
root@xiaotianbsp:/sys/kernel/debug/tracing# echo > trace   ## 清ringbuffer

## 3、查看trace
root@xiaotianbsp:/sys/kernel/debug/tracing# cat trace
# tracer: function_graph
#
# CPU  DURATION                  FUNCTION CALLS
# |     |   |                     |   |   |   |
root@xiaotianbsp:/sys/kernel/debug/tracing# echo 1 > tracing_on
root@xiaotianbsp:/sys/kernel/debug/tracing# cat trace
# tracer: function_graph
#
# CPU  DURATION                  FUNCTION CALLS
# |     |   |                     |   |   |   |
 4)               |  blk_start_request() {       ## 顯示函數(shù)內(nèi)部調(diào)用時(shí)間
 4)   1.166 us    |    blk_dequeue_request();
 4)   0.584 us    |    blk_add_timer();
 4) + 12.250 us   |  }
 4)               |  blk_start_request() {
 4)   1.166 us    |    blk_dequeue_request();
 4)   0.584 us    |    blk_add_timer();
 4) + 12.250 us   |  }

3、trace pid

下面介紹如何配置跟蹤進(jìn)程pid調(diào)用流程功能。

root@xiaotianbsp:~#cd /sys/kernel/debug/tracing/

## 1、配置tracer類型
root@xiaotianbsp:/sys/kernel/debug/tracing# echo 0 > tracing_on
root@xiaotianbsp:/sys/kernel/debug/tracing# cat available_tracers
blk branch function_graph wakeup_dl wakeup_rt wakeup irqsoff function nop
root@xiaotianbsp:/sys/kernel/debug/tracing# echo function_graph > current_tracer

## 2、設(shè)置tracer參數(shù)
root@xiaotianbsp:/sys/kernel/debug/tracing# ps -A | grep mmc
  155 ?        00:00:00 irq/27-mmc1
  157 ?        00:00:02 mmcqd/0             ## 跟蹤該pid
  182 ?        00:00:00 jbd2/mmcblk0p5-
root@xiaotianbsp:/sys/kernel/debug/tracing# echo 157 > set_ftrace_pid
root@xiaotianbsp:/sys/kernel/debug/tracing# echo 8 > max_graph_depth
root@xiaotianbsp:/sys/kernel/debug/tracing# echo > trace   ## 清ringbuffer

## 3、查看trace
root@xiaotianbsp:/sys/kernel/debug/tracing# cat trace
# tracer: function_graph
#
# CPU  DURATION                  FUNCTION CALLS
# |     |   |                     |   |   |   |
root@xiaotianbsp:/sys/kernel/debug/tracing# echo 1 > tracing_on
root@xiaotianbsp:/sys/kernel/debug/tracing# cat trace
# tracer: function_graph
#
# CPU  DURATION                  FUNCTION CALLS
# |     |   |                     |   |   |   |
...
 4)               |  blk_fetch_request() {              ## sd卡相關(guān)操作
 4)               |    blk_peek_request() {
 4)               |      deadline_dispatch_requests() {
 4)               |        deadline_remove_request.isra.0() {
 4)   0.584 us    |          elv_rb_del();
 4)   5.542 us    |        }
 4)               |        elv_dispatch_add_tail() {
 4)   0.292 us    |          elv_rqhash_del.isra.0();
 4)   5.542 us    |        }
 4) + 20.708 us   |      }
 4)               |      mmc_prep_request() {
 4)   0.583 us    |        mmc_access_rpmb();
 4)   5.834 us    |      }
 4) + 37.333 us   |    }
 4)               |    blk_start_request() {
 4)   0.875 us    |      blk_dequeue_request();
 4)   0.584 us    |      blk_add_timer();
 4) + 11.083 us   |    }
 4) + 57.750 us   |  }
...

其它類型后續(xù)介紹。

注:ftrace也可以用trace-cmd命令代替操作debugfs下的trace節(jié)點(diǎn)跟蹤,配合kernelshark,可圖形化分析數(shù)據(jù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容