这是命令 perf-script-python 可以使用我们的多个免费在线工作站之一在 OnWorks 免费托管服务提供商中运行,例如 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器
程序:
您的姓名
perf-script-python - 使用 Python 脚本处理跟踪数据
概要
PERF 脚本 [-s [Python]:脚本[.py]]
商品描述
这个 perf 脚本选项用于使用 perf 的内置 Python 处理 perf 脚本数据
口译员。 它读取和处理输入文件并显示跟踪结果
在给定的 Python 脚本中实现的分析(如果有)。
A 快 例
本节展示了从头到尾创建一个可运行的 Python 脚本的过程
从原始 perf 脚本流中聚合和提取有用的信息。 你可以避免
如果一个例子对你来说足够了,请阅读本文档的其余部分; 剩下的
文档提供了每个步骤的更多细节,并列出了可用的库函数
剧本作家。
这个例子实际上详细说明了用于创建 系统调用计数 脚本
当您通过以下方式列出可用的 perf 脚本脚本时,您会看到 PERF 脚本 -l. 如此一来,这
脚本还显示了如何将您的脚本集成到通用列表中 PERF
脚本 该命令列出的脚本。
syscall-counts 脚本是一个简单的脚本,但是展示了所有的基本思想
创建有用的脚本所必需的。 这是它的输出示例(系统调用名称是
尚不支持,它们将显示为数字):
.ft C
系统调用事件:
事件计数
----------------------------------------- ---------- ——
系统写入 455067
sys_getdents 4072
系统关闭 3037
第 1769 章
第 923 章
第 826 章
第 331 章
第 326 章
第 217 章
第 216 章
第 141 章
系统选择 102
系统轮询 84
sys_settimer 12
sys_writev 8
15 8
sys_lseek 7
sys_rt_sigprocmask 6
系统等待4 3
系统ioctl 3
sys_set_robust_list 1
系统退出 1
56 1
系统访问 1
英尺
基本上,我们的任务是保持每次系统调用时都会更新的每个系统调用记录
调用发生在系统中。 我们的脚本会做到这一点,但首先我们需要记录数据
将由该脚本处理。 理论上,我们可以通过以下几种方式
去做:
·我们可以启用tracing/events/syscalls目录下的每个事件,但这是
超过 600 个系统调用,远远超出 perf 允许的数量。 这些单独的系统调用
然而,如果我们想稍后使用我们从
用于深入了解并获取有关单个系统调用的更多详细信息的通用脚本
兴趣。
· 我们可以启用在下面找到的 sys_enter 和/或 sys_exit 系统调用
跟踪/事件/raw_syscalls。 这些被所有系统调用调用; 这 id 场可以是
用于区分各个系统调用号。
对于这个脚本,我们只需要知道输入了一个系统调用; 我们不在乎它如何
退出,所以我们将使用 PERF 记录 只记录 sys_enter 事件:
.ft C
# 性能记录 -a -e raw_syscalls:sys_enter
^C[ 性能记录:唤醒 1 次写入数据 ]
[性能记录:捕获并写入 56.545 MB perf.data(~2470503 个样本)]
英尺
这些选项基本上是说为系统范围内的每个系统调用事件收集数据,并且
将 per-cpu 输出多路复用到单个流中。 该单个流将被记录在
当前目录中名为 perf.data 的文件。
一旦我们有了包含数据的 perf.data 文件,我们就可以使用 -g PERF 脚本 选项
生成一个 Python 脚本,该脚本将包含在中找到的每个事件类型的回调处理程序
perf.data 跟踪流(有关更多详细信息,请参阅 STARTER SCRIPTS 部分)。
.ft C
# perf 脚本 -g python
生成的 Python 脚本: perf-script.py
同样在当前目录中创建的输出文件名为
性能脚本.py。 这是整个文件:
# perf 脚本事件处理程序,由 perf script -g python 生成
# 根据 GNU GPL 许可证第 2 版的条款获得许可
# common_* 事件处理程序字段是最常用的字段
# 所有事件。 它们不一定对应于“common_*”字段
# 在格式文件中。 那些不能用作处理程序参数的字段可以
# 使用 common_*(context) 形式的 Python 函数进行检索。
# 有关可用函数的列表,请参阅 perf-script-python 文档。
导入操作系统
导入系统
sys.path.append(os.environ['PERF_EXEC_PATH'] + \
'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
从 perf_trace_context 导入 *
从核心导入 *
定义 trace_begin():
打印“在 trace_begin”
定义跟踪结束():
打印“在 trace_end 中”
def raw_syscalls__sys_enter(事件名称,上下文,common_cpu,
common_secs、common_nsecs、common_pid、common_comm、
ID,参数):
打印头(事件名称,common_cpu,common_secs,common_nsecs,
common_pid、common_comm)
打印 "id=%d, args=%s\n" % \
(id, 参数),
def trace_unhandled(事件名称,上下文,common_cpu,common_secs,common_nsecs,
common_pid、common_comm):
打印头(事件名称,common_cpu,common_secs,common_nsecs,
common_pid、common_comm)
def print_header(event_name, cpu, secs, nsecs, pid, comm):
打印“%-20s %5u %05u.%09u %8u %-20s” % \
(事件名称、CPU、秒、纳秒、PID、通讯),
英尺
顶部是一个注释块,后面是一些导入语句和一个路径附加
每个 perf 脚本脚本都应该包括。
接下来是几个生成的函数,trace_begin() 和 trace_end(),它们是
分别在脚本的开头和结尾调用(有关详细信息,请参阅
SCRIPT_LAYOUT 部分)。
接下来是 活动 处理器 函数为每个事件生成一个 PERF
记录 输出。 处理程序函数采用子系统的形式事件名称, 和 包含 命名
参数, 一种 每 部分 in 此 事件; in Free Introduction 案件, 有 仅由 一种 事件,
原始系统调用系统输入()。 (有关事件的更多信息,请参阅下面的事件处理程序部分
处理程序)。
最后几个函数,就像开始和结束函数一样,为每个
脚本。 第一个,trace_unhandled(),每次脚本在
与脚本中的任何事件处理程序都不对应的 perf.data 文件。 这可以
意味着记录步骤记录了它并不真正感兴趣的事件类型,
或者脚本是针对与脚本不对应的跟踪文件运行的。
-g 选项生成的脚本只是为跟踪中找到的每个事件打印一行
流即它基本上只是将事件及其参数值转储到标准输出。 这
print_header() 函数只是一个用于该目的的实用函数。 让我们重命名
脚本并运行它以查看默认输出:
.ft C
# mv perf-script.py 系统调用计数.py
# perf 脚本 -s syscall-counts.py
raw_syscalls__sys_enter 1 00840.847582083 7506 perf id=1,args=
raw_syscalls__sys_enter 1 00840.847595764 7506 perf id=1,args=
raw_syscalls__sys_enter 1 00840.847620860 7506 perf id=1,args=
raw_syscalls__sys_enter 1 00840.847710478 6533 npviewer.bin id=78,args=
raw_syscalls__sys_enter 1 00840.847719204 6533 npviewer.bin id=142,args=
raw_syscalls__sys_enter 1 00840.847755445 6533 npviewer.bin id=3,args=
raw_syscalls__sys_enter 1 00840.847775601 6533 npviewer.bin id=3,args=
raw_syscalls__sys_enter 1 00840.847781820 6533 npviewer.bin id=3,args=
.
.
.
英尺
当然,对于这个脚本,我们对打印每个跟踪事件不感兴趣,而是
以一种有用的方式聚合它。 所以我们也将摆脱与印刷有关的一切
作为 trace_begin() 和 trace_unhandled() 函数,我们不会使用它们。 那留下
我们用这个简约的骨架:
.ft C
导入操作系统
导入系统
sys.path.append(os.environ['PERF_EXEC_PATH'] + \
'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
从 perf_trace_context 导入 *
从核心导入 *
定义跟踪结束():
打印“在 trace_end 中”
def raw_syscalls__sys_enter(事件名称,上下文,common_cpu,
common_secs、common_nsecs、common_pid、common_comm、
ID,参数):
英尺
在 trace_end() 中,我们将简单地打印结果,但首先我们需要生成一些结果
打印。 为此,我们需要让我们的 sys_enter() 处理程序进行必要的计数
直到所有事件都被计数。 由 syscall id 索引的哈希表是一个很好的方法
存储该信息; 每次调用 sys_enter() 处理程序时,我们只需增加
与由该系统调用 ID 索引的哈希条目关联的计数:
.ft C
系统调用 = autodict()
尝试:
系统调用[id] += 1
除了类型错误:
系统调用[id] = 1
英尺
系统调用 自律 object 是一种特殊的 Python 字典(在
Core.py) 实现 Perl 的 自动活化 Python 中的哈希值,即自动激活
散列,您可以分配嵌套的散列值,而不必费心去创建
中间级别,如果它们不存在,例如 syscalls[comm][pid][id] = 1 将创建
中间散列级别,最后将值 1 分配给散列条目 id (因为
被分配的值不是哈希对象本身,初始值在
类型错误异常。 好吧,在 Python 中可能有更好的方法来做到这一点,但这就是
暂时有效)。
将该代码放入 raw_syscalls__sys_enter() 处理程序中,我们实际上得到了一个
以 syscall id 为键的单级字典,并将计数作为值。
print_syscall_totals() 函数遍历字典中的条目并
为包含系统调用名称的每个条目显示一行(字典键包含
传递给 Util 函数 syscall_name() 的 syscall ids
原始系统调用号到相应的系统调用名称字符串)。 输出是
在处理完跟踪中的所有事件后显示,通过调用
来自在脚本末尾调用的 trace_end() 处理程序的 print_syscall_totals() 函数
处理。
生成上面显示的输出的最终脚本在下面完整显示
(syscall_name() 助手尚不可用,您现在只能处理 id):
.ft C
导入操作系统
导入系统
sys.path.append(os.environ['PERF_EXEC_PATH'] + \
'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
从 perf_trace_context 导入 *
从核心导入 *
从 Util 导入 *
系统调用 = autodict()
定义跟踪结束():
print_syscall_totals()
def raw_syscalls__sys_enter(事件名称,上下文,common_cpu,
common_secs、common_nsecs、common_pid、common_comm、
ID,参数):
尝试:
系统调用[id] += 1
除了类型错误:
系统调用[id] = 1
def print_syscall_totals():
如果 for_comm 不是 None:
打印 "\n %s 的系统调用事件:\n\n" % (for_comm),
其他:
打印 "\n系统调用事件:\n\n",
打印 "%-40s %10s\n" % ("event", "count"),
打印 "%-40s %10s\n" % ("--------------------------------- ---", \
"-----------"),
对于 id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \
反向 = 真):
打印 "%-40s %10d\n" % (syscall_name(id), val),
英尺
该脚本可以像以前一样运行:
# perf 脚本 -s syscall-counts.py
所以这些是编写和运行脚本的基本步骤。 该过程可以是
推广到您感兴趣的任何跟踪点或跟踪点集 - 基本上找到
通过查看显示的可用事件列表,您感兴趣的跟踪点
PERF 名单 和/或查看 /sys/kernel/debug/tracing events 以获取详细的事件和字段
info,使用记录相应的跟踪数据 PERF 记录, 传递给它的列表
有趣的事件,使用生成一个骨架脚本 PERF 脚本 -g 蟒蛇 并修改
代码来聚合和显示它以满足您的特定需求。
完成后,您可能会得到一个想要保留的通用脚本
周围并可供将来使用。 通过编写几个非常简单的 shell 脚本
并将它们放在正确的位置,您可以将您的脚本与其他脚本一起列出
列出的脚本 PERF 脚本 -l 命令例如:
.ft C
root@tropicana:~# 性能脚本 -l
可用跟踪脚本列表:
唤醒延迟系统范围的最小/最大/平均唤醒延迟
按文件读写程序的 r/w 活动,按文件
rw-by-pid 系统范围的 r/w 活动
英尺
这样做的一个很好的副作用是,您还可以捕获可能很长的 PERF
记录 记录脚本事件所需的命令。
让脚本显示为 内建的 脚本,您编写两个简单的脚本,一个用于
录音和一个 报告.
记录 script 是一个 shell 脚本,与您的脚本具有相同的基本名称,但具有
-附加记录。 shell 脚本应该放在 perf/scripts/python/bin
内核源代码树中的目录。 在那个脚本中,你写 PERF 记录
脚本所需的命令行:
.ft C
# cat 内核源代码/tools/perf/scripts/python/bin/syscall-counts-record
#!/ bin / bash
性能记录 -a -e raw_syscalls:sys_enter
英尺
报告 script 也是一个 shell 脚本,与您的脚本具有相同的基本名称,但具有
- 附上报告。 它也应该位于 perf/scripts/python/bin 目录中。 在
那个脚本,你写 PERF 脚本 -s 运行脚本所需的命令行:
.ft C
# cat 内核源代码/tools/perf/scripts/python/bin/syscall-counts-report
#!/ bin / bash
# 描述:系统范围的系统调用计数
性能脚本 -s 〜/libexec/perf-core/scripts/python/syscall-counts.py
英尺
请注意,shell 脚本中给出的 Python 脚本的位置在
libexec/perf-core/scripts/python 目录 - 这是脚本将被复制的地方
使 安装 当你安装 perf. 为了在那里安装脚本,
您的脚本需要位于内核源代码的 perf/scripts/python 目录中
树:
.ft C
# ls -al 内核源代码/工具/性能/脚本/python
root@tropicana:/home/trz/src/tip# ls -al tools/perf/scripts/python
总32
drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30。
drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 ..
drwxr-xr-x 2 trz trz 4096 2010-01-26 22:29 斌
-rw-r--r-- 1 trz trz 2548 2010-01-26 22:29 检查性能脚本.py
drwxr-xr-x 3 trz trz 4096 2010-01-26 22:49 Perf-Trace-Util
-rw-r--r-- 1 trz trz 1462 2010-01-26 22:30 系统调用计数.py
英尺
一旦你这样做了(不要忘记做一个新的 使 安装, 否则你的脚本不会
在运行时出现), PERF 脚本 -l 应该为您的脚本显示一个新条目:
.ft C
root@tropicana:~# 性能脚本 -l
可用跟踪脚本列表:
唤醒延迟系统范围的最小/最大/平均唤醒延迟
按文件读写程序的 r/w 活动,按文件
rw-by-pid 系统范围的 r/w 活动
syscall-counts 系统范围的系统调用计数
英尺
您现在可以通过执行记录步骤 PERF 脚本 记录:
# perf 脚本记录系统调用计数
并使用显示输出 PERF 脚本 报告:
# perf 脚本报告系统调用计数
起动机 脚本
您可以通过以下方式快速开始为一组特定的跟踪数据编写脚本
使用生成框架脚本 PERF 脚本 -g 蟒蛇 在与一个相同的目录中
现有的 perf.data 跟踪文件。 这将生成一个包含处理程序的启动脚本
对于跟踪文件中的每个事件类型; 它只是打印每个可用的字段
跟踪文件中的每个事件。
您还可以查看现有的脚本 〜/ libexec / perf-core /脚本/ python
展示如何进行基本操作的典型示例,例如聚合事件数据、打印结果、
等等。此外,check-perf-script.py 脚本,虽然它的结果并不有趣,
尝试练习所有主要的脚本功能。
EVENT 搬运工
当使用跟踪脚本调用 perf 脚本时,用户定义的 处理器 功能 is
为跟踪中的每个事件调用。 如果没有为给定的处理函数定义
事件类型,事件被忽略(或传递给 跟踪处理 功能,见下文)和
处理下一个事件。
大多数事件的字段值作为参数传递给处理函数; 一些
不太常见的不是 - 这些可作为回调到 perf 可执行文件
(见下文)。
例如,下面的 perf record 命令可以用来记录所有的 sched_wakeup
系统中的事件:
# 性能记录 -a -e sched:sched_wakeup
应使用上述选项记录要使用脚本处理的跟踪:-a
以启用系统范围的收集。
sched_wakep 事件的格式文件定义了以下字段(请参阅
/sys/kernel/debug/tracing/events/sched/sched_wakeup/format):
.ft C
格式:
字段:unsigned short common_type;
字段:unsigned char common_flags;
字段:unsigned char common_preempt_count;
字段:int common_pid;
字段:字符通信[TASK_COMM_LEN];
字段:pid_t pid;
字段:int prio;
字段:int 成功;
字段:int target_cpu;
英尺
此事件的处理函数将定义为:
.ft C
def sched__sched_wakeup(事件名称,上下文,common_cpu,common_secs,
common_nsecs、common_pid、common_comm、
comm、pid、prio、success、target_cpu):
通过
英尺
处理函数采用subsystem__event_name 的形式。
处理程序参数列表中的 common_* 参数是传递给的参数集
所有事件处理程序; 一些字段对应于格式中的 common_* 字段
文件,但有些是综合的,有些 common_* 字段不够常见,无法
作为参数传递给每个事件,但可以作为库函数使用。
以下是每个不变事件参数的简要说明:
event_name 文本形式的事件名称
context 一个不透明的“cookie”,用于回调 perf
common_cpu 事件发生的 CPU
common_secs 事件时间戳的秒部分
common_nsecs 事件时间戳的 nsecs 部分
common_pid 当前任务的pid
common_comm 当前进程的名称
事件格式文件中的所有剩余字段都有对应的处理程序
同名的函数参数,如上例所示。
以上提供了直接访问每个事件的每个字段所需的基础知识
跟踪,它涵盖了编写有用的跟踪脚本所需了解的 90%。 这
下面的部分涵盖了其余部分。
SCRIPT 布局
每个 perf 脚本 Python 脚本都应该从设置 Python 模块搜索路径开始,然后
'导入'一些支持模块(见下面的模块描述):
.ft C
导入操作系统
导入系统
sys.path.append(os.environ['PERF_EXEC_PATH'] + \
'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
从 perf_trace_context 导入 *
从核心导入 *
英尺
脚本的其余部分可以按任何顺序包含处理程序函数和支持函数。
除了上面讨论的事件处理函数之外,每个脚本都可以实现一个集合
可选功能:
跟踪_开始,如果已定义,则在处理任何事件之前调用并为脚本提供
有机会做设置任务:
.ft C
def trace_begin:
通过
英尺
跟踪结束,如果已定义,则在处理完所有事件后调用并为脚本提供
有机会执行脚本结束任务,例如显示结果:
.ft C
定义跟踪结束:
通过
英尺
跟踪未处理,如果已定义,则在任何没有处理程序的事件之后调用
为它明确定义。 标准的公共参数集被传递给它:
.ft C
def trace_unhandled(事件名称、上下文、common_cpu、common_secs、
common_nsecs、common_pid、common_comm):
通过
英尺
其余部分提供了每个可用的内置 perf 脚本的描述
Python 模块及其相关功能。
可用 课程结构 AND 职能
以下部分描述了通过各种性能可用的函数和变量
脚本 Python 模块。 要使用给定模块中的函数和变量,请添加
相应 止 XXXX 进口 行到您的 perf 脚本脚本。
核心文件 模块
这些函数为用户脚本提供了一些基本功能。
标志_str 和 符号字符串 函数为标志和符号提供人类可读的字符串
领域。 这些对应于从 打印 fmt 的领域
事件格式文件:
flag_str(event_name, field_name, field_value) - 返回事件 event_name 的标志字段 field_name 的 field_value 对应的字符串表示
symbol_str(event_name, field_name, field_value) - 为事件 event_name 的符号字段 field_name 返回与 field_value 对应的字符串表示
自律 函数返回一种特殊的 Python 字典,它实现了 Perl 的
自动活化 Python 中的哈希值,即具有自动激活哈希值,您可以分配嵌套哈希值
值而不必费心创建中间级别,如果他们不这样做
存在。
autodict() - 返回一个自动激活的字典实例
性能跟踪上下文 模块
一些 常见 事件格式文件中的字段并不是那么常见,但需要
尽管如此,仍可访问用户脚本。
perf_trace_context 定义了一组函数,可用于在
当前事件的上下文。 这些函数中的每一个都需要一个上下文变量,它是
与作为第二个参数传递给每个事件处理程序的上下文变量相同。
common_pc(context) - 返回当前事件的 common_preempt 计数
common_flags(context) - 返回当前事件的 common_flags
common_lock_depth(context) - 返回当前事件的 common_lock_depth
实用程序 模块
与 perf 脚本一起使用的各种实用函数:
nsecs(secs, nsecs) - 返回给定 secs/nsecs 对的总 nsecs
nsecs_secs(nsecs) - 返回给定 nsecs 的整个 secs 部分
nsecs_nsecs(nsecs) - 返回给定 nsecs 的 nsecs 余数
nsecs_str(nsecs) - 以 secs.nsecs 的形式返回可打印的字符串
avg(total, n) - 返回给定总和和值总数的平均值
使用 onworks.net 服务在线使用 perf-script-python