宋寶華:關於Ftrace的一個完整案例【轉】

来源:https://www.cnblogs.com/linhaostudy/archive/2018/12/31/10202640.html
-Advertisement-
Play Games

Ftrace簡介 Ftrace是Linux進行代碼級實踐分析最有效的工具之一,比如我們進行一個系統調用,出來的時間過長,我們想知道時間花哪裡去了,利用Ftrace就可以追蹤到一級級的時間分佈。 Ftrace案例 寫一個proc模塊,包含一個proc的讀和寫的入口。test_proc_show()故意 ...


Ftrace簡介

Ftrace是Linux進行代碼級實踐分析最有效的工具之一,比如我們進行一個系統調用,出來的時間過長,我們想知道時間花哪裡去了,利用Ftrace就可以追蹤到一級級的時間分佈。

Ftrace案例

寫一個proc模塊,包含一個proc的讀和寫的入口。test_proc_show()故意調用了一個kill_time()的函數,而kill_time()的函數,又調用了mdelay(2)和kill_moretime()的函數,該函數體內調用mdelay(2)。

kill_time()的函數和kill_moretime()函數前面都加了noinline以避免被編譯器inline優化掉。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
 
static unsigned int variable;
static struct proc_dir_entry *test_dir, *test_entry;
 
static noinline void kill_moretime(void)
{
mdelay(2);
}
static noinline void kill_time(void)
{
mdelay(2);
kill_moretime();
}
 
static int test_proc_show(struct seq_file *seq, void *v)
{
unsigned int *ptr_var = seq->private;
kill_time();
seq_printf(seq, "%u\n", *ptr_var);
return 0;
}
 
static ssize_t test_proc_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
...
}
 
static int test_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, test_proc_show, PDE_DATA(inode));
}
static const struct file_operations test_proc_fops =
{
.owner = THIS_MODULE,
.open = test_proc_open,
.read = seq_read,
.write = test_proc_write,
.llseek = seq_lseek,
.release = single_release,
};
 
static __init int test_proc_init(void)
{
test_dir = proc_mkdir("test_dir", NULL);
if (test_dir) {
test_entry = proc_create_data("test_rw",0666, test_dir, &test_proc_fops, &variable);
if (test_entry)
return 0;
}
 
return -ENOMEM;
}
module_init(test_proc_init);
static __exit void test_proc_cleanup(void)
{
remove_proc_entry("test_rw", test_dir);
remove_proc_entry("test_dir", NULL);
}
module_exit(test_proc_cleanup);
 
 
MODULE_AUTHOR("Barry Song <[email protected]>");
MODULE_DESCRIPTION("proc exmaple");
MODULE_LICENSE("GPL v2");

模塊對應的Makefile如下:

KVERS = $(shell uname -r)

# Kernel modules

obj-m += proc.o

# Specify flags for the module compilation.

#EXTRA_CFLAGS=-g -O0

build: kernel_modules
kernel_modules:
 make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules
clean:
 make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean

編譯並且載入:

$ make
baohua@baohua-perf:~/develop/training/debug/ftrace/proc$ $ sudo insmod proc.ko

[sudo] password for baohua: 

之後/proc目錄下/proc/test_dir/test_rw文件可被讀寫。

下麵我們用Ftrace來跟蹤test_proc_show()這個函數。

我們把啟動ftrace的所有命令寫到一個腳本function.sh裡面:

#!/bin/bash
debugfs=/sys/kernel/debug

echo nop > $debugfs/tracing/current_tracer

echo 0 > $debugfs/tracing/tracing_on

echo $$ > $debugfs/tracing/set_ftrace_pid

echo function_graph > $debugfs/tracing/current_tracer

#replace test_proc_show by your function name

echo test_proc_show > $debugfs/tracing/set_graph_function

echo 1 > $debugfs/tracing/tracing_on

然後用這個腳本去啟動cat /proc/test_dir/test_rw,這樣ftrace下麵test_proc_show()函數就被trace了。

# ./function.sh cat /proc/test_dir/test_rw

讀取trace的結果:

# cat /sys/kernel/debug/tracing/trace > 1

接著用vim打開這個文件1,發現這個文件有600多行:

Ftrace結果怎麼讀?

Ftrace結果怎麼讀?答案非常簡單:如果是葉子函數,就直接在這個函數的前面顯示它占用的時間,如果是非葉子,要等到 }的時候,再顯示時間,如下圖:

延遲比較大的部分,會有+、#等特殊標號:

'$' - greater than 1 second
 '@' - greater than 100 milisecond
 '*' - greater than 10 milisecond
 '#' - greater than 1000 microsecond
 '!' - greater than 100 microsecond
 '+' - greater than 10 microsecond
 ' ' - less than or equal to 10 microsecond.

vim對Ftrace進行摺疊

上面那個Ftrace文件太大了,大到看不清。我們可以用vim來摺疊之,不過需要一個vim的特別配置,我把它存放在了我的~目錄,名字叫.fungraph-vim:

" Enable folding for ftrace function_graph traces.

"

" To use, :source this file while viewing a function_graph trace, or use vim's

" -S option to load from the command-line together with a trace.  You can then

" use the usual vim fold commands, such as "za", to open and close nested

" functions.  While closed, a fold will show the total time taken for a call,

" as would normally appear on the line with the closing brace.  Folded

" functions will not include finish_task_switch(), so folding should remain

" relatively sane even through a context switch.

"

" Note that this will almost certainly only work well with a

" single-CPU trace (e.g. trace-cmd report --cpu 1).



function! FunctionGraphFoldExpr(lnum)

  let line = getline(a:lnum)

  if line[-1:] == '{'

    if line =~ 'finish_task_switch() {$'

      return '>1'

    endif

    return 'a1'

  elseif line[-1:] == '}'

    return 's1'

  else

    return '='

  endif

endfunction



function! FunctionGraphFoldText()

  let s = split(getline(v:foldstart), '|', 1)

  if getline(v:foldend+1) =~ 'finish_task_switch() {$'

    let s[2] = ' task switch  '

  else

    let e = split(getline(v:foldend), '|', 1)

    let s[2] = e[2]

  endif

  return join(s, '|')

endfunction



setlocal foldexpr=FunctionGraphFoldExpr(v:lnum)

setlocal foldtext=FunctionGraphFoldText()

setlocal foldcolumn=12

setlocal foldmethod=expr

之後我們配置vim為這個模板來打開前面那個600多行的文件1:

 vim -S ~/.fungraph-vim 1

這樣我們看到的樣子是:

我們可以把游標移動到第5行,鍵盤敲打za,則展開為:

我們可以用z、a兩個按鍵,搜索或者展開Ftrace的結果。

最後,https://github.com/brendangregg/perf-tools對Ftrace的功能進行了很好的封裝和集成,建議大家用perf-tools來使用Ftrace,則效果更佳更簡單。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 任何使用 async/await 進行修飾的方法,都會被認為是一個非同步方法;實際上,這些非同步方法都是基於隊列的線程任務,從你開始使用 Task 去運行一段代碼的時候,實際上就相當於開啟了一個線程,預設情況下,這個線程數由線程池 ThreadPool 進行管理的。 ...
  • 載入超過100M的xml文件時(可能不是很常見),XmlDocument這種全部載入到記憶體里的模式就有點不友好了,耗時長、記憶體高。 這時用xmlreader就會有自行車換超跑的感覺,但其間遇到幾個坑,記錄一下。 先看源碼,包括dom和sax兩種模式的讀取和寫入 DOM模式: SAX(simple A ...
  • 概述 Microsoft.AspNetCore.NodeServices庫 實例 新建aspnet core站點 添加nuget包 建立node環境,此處示例用於掃描wifi環境 建立nodejs的程式文件 index.js 設置js文件為始終複製 註入配置 在控制器-Action處調用 返回情況 ...
  • 前言 2018年還有幾天就結束了,回顧一下今年的博客blog-posts, 簡單整理一下行業與軟體過程(Software Industry & process improvement) 關註軟體過程改進到效能改進,除了軟體開發,還是軟體測試。全球Scrum在應用中,全球軟體測試行業演化;不必多說,研... ...
  • 1. 前言 KASAN是一個動態檢測記憶體錯誤的工具。KASAN可以檢測全局變數、棧、堆分配的記憶體發生越界訪問等問題。功能比SLUB DEBUG齊全並且支持實時檢測。越界訪問的嚴重性和危害性通過我之前的文章(SLUB DEBUG技術)應該有所瞭解。正是由於SLUB DEBUG缺陷,因此我們需要一種更加 ...
  • 1、首先查找tomcat目錄 ? 1 sudo find / -name *shutdown.sh* ? 1 sudo find / -name *shutdown.sh* ? 1 sudo find / -name *shutdown.sh* ? 1 sudo find / -name *shut ...
  • lfs學習筆記(三)鏈接:https://www.cnblogs.com/renren-study-notes/p/10199381.html 一名linux愛好者,記錄構建Linux From Scratch的過程 經博客園-駿馬金龍前輩介紹,開始接觸學習lfs,用博客記錄學習筆記,如有寫的不恰當 ...
  • 一名linux愛好者,記錄構建Linux From Scratch的過程 經博客園-駿馬金龍前輩介紹,開始接觸學習lfs,用博客記錄學習筆記,如有寫的不恰當的地方,望多多指正。筆記中只是記錄一些問題和書中表述不清晰的內容的處理辦法以及我的解決思路,僅做參考。 要實際構建lfs請結合lfs官方的書籍操 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...