perf的选项来衡量用户和内核级别的事件是什么意思?

Linux perf工具提供对CPU事件计数器的访问。 它允许您指定要计数的事件以及计算这些事件的时间。

https://perf.wiki.kernel.org/index.php/Tutorial

默认情况下,事件在用户级和内核级都被测量:

perf stat -e cycles dd if=/dev/zero of=/dev/null count=100000

要仅在用户级别进行测量,需要传递一个修饰符:

perf stat -e cycles:u dd if=/dev/zero of=/dev/null count=100000

测量用户和内核(明确):

perf stat -e cycles:uk dd if=/dev/zero of=/dev/null count=100000

由此,我预计cycles:u意思是“在运行非内核代码时只计数事件”,记录的计数不会映射到内核符号,但似乎并非如此。

这是一个例子:

perf record -e cycles:u du -sh ~
[...]
perf report --stdio -i perf.data
[...]
9.24%  du       [kernel.kallsyms]  [k] system_call
[...]
0.70%  du       [kernel.kallsyms]  [k] page_fault
[...]

如果我这样做,但使用cycles:uk然后我得到更多的内核符号报告,所以事件修饰符确实有影响。 使用cycles:k几乎专门生成内核符号,但它包含几个libc符号。

这里发生了什么? 这是预期的行为? 我误解了链接文档中使用的语言吗?

链接的文档还包括这个表格,如果有帮助,它使用略有不同的描述:

Modifiers | Description                          | Example
----------+--------------------------------------+----------
u         | monitor at priv level 3, 2, 1 (user) | event:u
k         | monitor at priv level 0 (kernel)     | event:k

编辑:更多信息:

CPU是Intel Haswell。 具体型号是i7-5820K。

Distro是最新的Arch Linux(滚动发布时间表)与内核4.1.6。

perf本身的版本是4.2.0。

EDIT2:

来自示例运行的更多输出。 正如你所看到的, cycles:u主要报告非内核符号。 我知道,当您查看带注释的程序集输出时,有时会将错误的属性计数到相邻的指令。 也许这是相关的?

周期:U

# perf record -e cycles:u du -sh ~
179G    /home/khouli
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.116 MB perf.data (2755 samples) ]
# sudo perf report --stdio -i perf.data
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 2K of event 'cycles:u'
# Event count (approx.): 661835375
#
# Overhead  Command  Shared Object      Symbol
# ........  .......  .................  ..............................
#
    11.02%  du       libc-2.22.so       [.] _int_malloc
     9.73%  du       libc-2.22.so       [.] _int_free
     9.24%  du       du                 [.] fts_read
     9.23%  du       [kernel.kallsyms]  [k] system_call
     4.17%  du       libc-2.22.so       [.] strlen
     4.17%  du       libc-2.22.so       [.] __memmove_sse2
     3.47%  du       libc-2.22.so       [.] __readdir64
     3.33%  du       libc-2.22.so       [.] malloc_consolidate
     2.87%  du       libc-2.22.so       [.] malloc
     1.83%  du       libc-2.22.so       [.] msort_with_tmp.part.0
     1.63%  du       libc-2.22.so       [.] __memcpy_avx_unaligned
     1.63%  du       libc-2.22.so       [.] __getdents64
     1.52%  du       libc-2.22.so       [.] free
     1.47%  du       libc-2.22.so       [.] __memmove_avx_unaligned
     1.44%  du       du                 [.] 0x000000000000e609
     1.41%  du       libc-2.22.so       [.] _wordcopy_bwd_dest_aligned
     1.19%  du       du                 [.] 0x000000000000e644
     0.93%  du       libc-2.22.so       [.] __fxstatat64
     0.85%  du       libc-2.22.so       [.] do_fcntl
     0.73%  du       [kernel.kallsyms]  [k] page_fault
[lots more symbols, almost all in du...]

周期:英国

# perf record -e cycles:uk du -sh ~
179G    /home/khouli
[ perf record: Woken up 1 times to write data ]
[ext4] with build id 0f47443e26a238299e8a5963737da23dd3530376 not found,
continuing without symbols
[ perf record: Captured and wrote 0.120 MB perf.data (2856 samples) ]
# perf report --stdio -i perf.data
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 2K of event 'cycles:uk'
# Event count (approx.): 3118065867
#
# Overhead  Command  Shared Object      Symbol
# ........  .......  .................  ..............................................
#
    13.80%  du       [kernel.kallsyms]  [k] __d_lookup_rcu
     6.16%  du       [kernel.kallsyms]  [k] security_inode_getattr
     2.52%  du       [kernel.kallsyms]  [k] str2hashbuf_signed
     2.43%  du       [kernel.kallsyms]  [k] system_call
     2.35%  du       [kernel.kallsyms]  [k] half_md4_transform
     2.31%  du       [kernel.kallsyms]  [k] ext4_htree_store_dirent
     1.97%  du       [kernel.kallsyms]  [k] copy_user_enhanced_fast_string
     1.96%  du       libc-2.22.so       [.] _int_malloc
     1.93%  du       du                 [.] fts_read
     1.90%  du       [kernel.kallsyms]  [k] system_call_after_swapgs
     1.83%  du       libc-2.22.so       [.] _int_free
     1.44%  du       [kernel.kallsyms]  [k] link_path_walk
     1.33%  du       libc-2.22.so       [.] __memmove_sse2
     1.19%  du       [kernel.kallsyms]  [k] _raw_spin_lock
     1.19%  du       [kernel.kallsyms]  [k] __fget_light
     1.12%  du       [kernel.kallsyms]  [k] kmem_cache_alloc
     1.12%  du       [kernel.kallsyms]  [k] __ext4_check_dir_entry
     1.05%  du       [kernel.kallsyms]  [k] lockref_get_not_dead
     1.02%  du       [kernel.kallsyms]  [k] generic_fillattr
     0.95%  du       [kernel.kallsyms]  [k] do_dentry_open
     0.95%  du       [kernel.kallsyms]  [k] path_init
     0.95%  du       [kernel.kallsyms]  [k] lockref_put_return
     0.91%  du       libc-2.22.so       [.] do_fcntl
     0.91%  du       [kernel.kallsyms]  [k] ext4_getattr
     0.91%  du       [kernel.kallsyms]  [k] rb_insert_color
     0.88%  du       [kernel.kallsyms]  [k] __kmalloc
     0.88%  du       libc-2.22.so       [.] __readdir64
     0.88%  du       libc-2.22.so       [.] malloc
     0.84%  du       [kernel.kallsyms]  [k] ext4fs_dirhash
     0.84%  du       [kernel.kallsyms]  [k] __slab_free
     0.84%  du       [kernel.kallsyms]  [k] in_group_p
     0.81%  du       [kernel.kallsyms]  [k] get_empty_filp
     0.77%  du       libc-2.22.so       [.] malloc_consolidate
[more...]

周期:K

# perf record -e cycles:k du -sh ~
179G    /home/khouli
[ perf record: Woken up 1 times to write data ]
[ext4] with build id 0f47443e26a238299e8a5963737da23dd3530376 not found, continuing
without symbols
[ perf record: Captured and wrote 0.118 MB perf.data (2816 samples) ]
# perf report --stdio -i perf.data
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 2K of event 'cycles:k'
# Event count (approx.): 2438426748
#
# Overhead  Command  Shared Object      Symbol
# ........  .......  .................  ..............................................
#
    17.11%  du       [kernel.kallsyms]  [k] __d_lookup_rcu
     6.97%  du       [kernel.kallsyms]  [k] security_inode_getattr
     4.22%  du       [kernel.kallsyms]  [k] half_md4_transform
     3.10%  du       [kernel.kallsyms]  [k] str2hashbuf_signed
     3.01%  du       [kernel.kallsyms]  [k] system_call_after_swapgs
     2.59%  du       [kernel.kallsyms]  [k] ext4_htree_store_dirent
     2.24%  du       [kernel.kallsyms]  [k] copy_user_enhanced_fast_string
     2.14%  du       [kernel.kallsyms]  [k] lockref_get_not_dead
     1.86%  du       [kernel.kallsyms]  [k] ext4_getattr
     1.85%  du       [kernel.kallsyms]  [k] kfree
     1.68%  du       [kernel.kallsyms]  [k] __ext4_check_dir_entry
     1.53%  du       [kernel.kallsyms]  [k] __fget_light
     1.34%  du       [kernel.kallsyms]  [k] link_path_walk
     1.34%  du       [kernel.kallsyms]  [k] path_init
     1.22%  du       [kernel.kallsyms]  [k] __kmalloc
     1.22%  du       [kernel.kallsyms]  [k] kmem_cache_alloc
     1.14%  du       [kernel.kallsyms]  [k] do_dentry_open
     1.11%  du       [kernel.kallsyms]  [k] ext4_readdir
     1.07%  du       [kernel.kallsyms]  [k] __find_get_block_slow
     1.07%  du       libc-2.22.so       [.] do_fcntl
     1.04%  du       [kernel.kallsyms]  [k] _raw_spin_lock
     0.99%  du       [kernel.kallsyms]  [k] _raw_read_lock
     0.95%  du       libc-2.22.so       [.] __fxstatat64
     0.94%  du       [kernel.kallsyms]  [k] rb_insert_color
     0.94%  du       [kernel.kallsyms]  [k] generic_fillattr
     0.93%  du       [kernel.kallsyms]  [k] ext4fs_dirhash
     0.93%  du       [kernel.kallsyms]  [k] find_get_entry
     0.89%  du       [kernel.kallsyms]  [k] rb_next
     0.89%  du       [kernel.kallsyms]  [k] is_dx_dir
     0.89%  du       [kernel.kallsyms]  [k] in_group_p
     0.89%  du       [kernel.kallsyms]  [k] cp_new_stat
   [more...]

perf_event_paranoid

$ cat /proc/sys/kernel/perf_event_paranoid
1

内核配置为perf

$ cat /proc/config.gz | gunzip | grep -A70 'Kernel Perf'
# Kernel Performance Events And Counters
#
CONFIG_PERF_EVENTS=y
# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_COMPAT_BRK is not set
# CONFIG_SLAB is not set
CONFIG_SLUB=y
CONFIG_SLUB_CPU_PARTIAL=y
CONFIG_SYSTEM_TRUSTED_KEYRING=y
CONFIG_PROFILING=y
CONFIG_TRACEPOINTS=y
CONFIG_OPROFILE=m
# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_OPROFILE_NMI_TIMER=y
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
CONFIG_KPROBES_ON_FTRACE=y
CONFIG_UPROBES=y
# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_ARCH_USE_BUILTIN_BSWAP=y
CONFIG_KRETPROBES=y
CONFIG_USER_RETURN_NOTIFIER=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_OPTPROBES=y
CONFIG_HAVE_KPROBES_ON_FTRACE=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_DMA_CONTIGUOUS=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_HW_BREAKPOINT=y
CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
CONFIG_HAVE_USER_RETURN_NOTIFIER=y
CONFIG_HAVE_PERF_EVENTS_NMI=y
CONFIG_HAVE_PERF_REGS=y
CONFIG_HAVE_PERF_USER_STACK_DUMP=y
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
CONFIG_HAVE_CMPXCHG_LOCAL=y
CONFIG_HAVE_CMPXCHG_DOUBLE=y
CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_SECCOMP_FILTER=y
CONFIG_HAVE_CC_STACKPROTECTOR=y
CONFIG_CC_STACKPROTECTOR=y
# CONFIG_CC_STACKPROTECTOR_NONE is not set
# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
CONFIG_CC_STACKPROTECTOR_STRONG=y
CONFIG_HAVE_CONTEXT_TRACKING=y
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
CONFIG_HAVE_ARCH_HUGE_VMAP=y
CONFIG_HAVE_ARCH_SOFT_DIRTY=y
CONFIG_MODULES_USE_ELF_RELA=y
CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_COMPAT_OLD_SIGACTION=y

我理解你的问题是:为什么用户模式记录的perf显示内核内的值? 那么,从“系统会计”的角度来看,它正在做它应该做的事情。

你做到了: perf record -e cycles:u du -sh ~ page_fault你在system_callpage_fault上得到了统计信息,你想知道为什么会发生这种情况?

当你做了du ,它必须遍历文件系统。 在这样做时,它发出系统调用它所需的东西(例如打开,readdir等)。 杜为你发起了这些事情,所以它被“收回”了。 同样,杜页错误了很多次。

perf正在跟踪由给定进程/程序引起的任何活动,即使它发生在内核地址空间内。 换句话说,程序请求了这个活动,内核根据程序的要求执行了它,所以它得到适当的收费。 内核必须做“真正的工作”才能执行FS I / O和/或解决页面错误,因此您必须“为您委托的工作付费”。 任何一个给定的程序所消耗的系统资源都会被计入。

这是计算机系统的标准会计模型,可以追溯到20世纪60年代,当时人们在大型计算机上实际租用了时间。 你直接或间接地为你所做的一切收费(就像律师:-)]。
*每分钟的连接时间收费
*用户程序中消耗的每CPU周期收费
*为内核空间中的程序执行的每cpu周期收费
*收取每个网络数据包的费用
*由您的程序引起的任何页面错误收费
*为每个读取/写入的磁盘块收费,无论是文件还是分页/交换磁盘
在本月底,他们邮寄了一份分项账单(就像公用事业账单一样),而且你必须支付:
真正的钱。

请注意,有些事情不会收取费用。 例如,让我们假设你的程序是受计算限制的,但不会执行[很多] I / O并使用相对较少的内存(即它本身不会导致页面错误)。 该程序将收取用户空间CPU使用费。

操作系统可能不得不换出一个或多个页面,以腾出一些其他内存程序的空间。 生猪运行后,您的程序将再次运行。 您的程序将需要在从其中盗取的页面或页面中进行故障排除。

由于您的程序不会导致页面错误,您的程序不会因此收费。 换句话说,对于每一个从您那里“被盗”的页面,当您的程序必须重新启动时,您会获得该页面的“功劳”。

另外,当试图运行不同的进程时,内核不会将其进程调度程序消耗的CPU时间记入任何进程。 这被认为是“管理费用”和/或标准运营成本。 例如,如果您在银行拥有支票账户,他们不会向您收取您访问的当地分支机构的维护费用。

因此,虽然perf是用于衡量绩效的,但它使用会计模型来获取数据。

这就像一辆汽车。 你可以开车去商店买东西,然后你会消耗一些汽油。 或者,你可以让一个朋友把你的车开到商店。 在任何一种情况下,因为驾驶汽车,你必须支付汽油费,或者因为(当朋友驾车时)汽油在为你做某事时被消耗。 在这种情况下,内核就是你的朋友:-)

更新:

我的源代码是源代码[内核源代码]。 而且,我已经做了40年的内核编程。

有两种基本类型的性能计数器。 内核可以生成的“宏”页面错误等。 其他人是系统调用计数器。

另一次是“微型”或“纳米”型。 这些来自x86的PMC架构,并且具有计数器,用于诸如“缓存未命中”,“分支错误预测”,“数据获取错误预测”等内核无法计算的内容。

PMC计数器只是自由运行。 这就是为什么你得到你的全球统计数据,而不管你在做什么录制模式。 内核可以定期询问它们,但每次PMC递增时都无法控制。 是否需要这些的全局/系统范围和/或每个CPU值? 只需执行适当的RDPMC指令即可。

要跟踪进程的PMC,在启动进程时,执行RDPMC并将任务结构中的值(对于标记为“感兴趣”的许多值)保存为“启动时的PMC值”。 当给定的CPU核心重新计划时,调度程序计算“下一个”任务,调度程序获取当前的PMC值,当它启动该任务时获取当前PMC值与存储在“旧”任务块中的值之间的差值,并且碰撞该任务对该PMC的“总计数”。 “当前值”成为新任务的“开始时的PMC值”

在Linux中,当发生任务/上下文切换时,它会生成两个perf事件,一个用于“在CPU X上输入新任务”和“在CPU X上停止旧任务”。

你的问题是为什么监视“用户模式”产生内核地址。 这是因为在录制时(并且不是perf程序),它将临时数据[如上所述]存储在当前任务/上下文块中,直到实际发生任务切换。

关键要注意的是,这个上下文不会因为系统调用被执行而改变 - 只有当上下文切换发生时才会执行。 例如,gettimeofday syscall只是获取挂钟时间并将其返回给用户空间。 它不会执行上下文切换,因此任何启动的perf事件都将被收取到活动/当前上下文中。 无论它来自内核空间还是用户空间都无关紧要。

作为另一个例子,假设进程执行一个文件读取系统调用。 在遍历文件句柄数据,inode等时,它可能会产生几个perf事件。 此外,它可能会产生更多的缓存未命中和其他PMC计数器颠簸。 如果所需的块已经在FS块缓存中,则系统调用只会执行copy_to_user,然后重新输入用户空间。 由于pmc_value_at_start仍然有效,所以没有昂贵的上下文切换与上述PMC差异计算。

这样做的原因之一是性能[perf机制]。 如果您在系统调用启动后跨越内核空间时立即执行了PMC保存/恢复操作[将内核统计信息与给定进程的用户统计信息分开,如您所愿],则开销将非常巨大。 你不会是测量基本内核的性能。 你会是测量内核的性能+大量的性能开销。

当我不得不对基于Linux的商用硬实时系统进行性能分析时,我开发了自己的性能测井系统。 该系统具有8个CPU内核,可与多个FPGA的PCIe总线上的多个定制硬件板进行交互。 FPGA还具有在Microblaze内运行的定制固件。 来自用户空间,内核空间和microblaze的事件日志都可以时间协调为纳秒级分辨率,存储事件记录的时间为70ns。

对我来说,Linux的perf机制有点粗糙和臃肿。 如果要使用它来尝试排除涉及竞争条件的性能/计时错误,可能的锁定/解锁问题等,则可能会产生问题。 也就是说,没有perf的情况下运行系统,你会得到错误。 打开perf,你不会因为你改变了系统的基本特征时间。 关闭perf,并重新出现计时错误。


这里发生了什么? 这是预期的行为? 我误解了链接文档中使用的语言吗?

在链接中提到的内核和处理器方面似乎存在很大差异,并且正在用于评估。

链接https://perf.wiki.kernel.org/index.php/Tutorial中的介绍部分指出:“输出是在具有内核2.6.38-8的Ubuntu 11.04系统上获得的 - 通用结果在HP 6710b上运行,具有双重核心英特尔酷睿2 T7100 CPU)“,而目前的评测是基于Arch Linux发行版的Intel Haswell(i7-5820K - 6核心),内核为4.1.6。

排除行为和文档差异的选项之一是在链接https://perf.wiki.kernel.org/index.php/Tutorial的介绍部分中提到的具有等效配置的系统上进行测试。

链接地址: http://www.djcxy.com/p/80037.html

上一篇: What does perf's option to measure events at user and kernel levels mean?

下一篇: space variables at "perf" events