我想通过SystemTap(#cache引用,#cache未命中等)来剖析内核模块的caching行为。 在线示例脚本显示了SystemTap如何用于读取perf事件和计数器,包括与caching相关的脚本: https : //sourceware.org/systemtap/examples/profiling/perf.stp
此示例脚本默认情况下适用于进程:
probe perf.hw.cache_references.process("/usr/bin/find").counter("find_insns") {}
我用module
replace了process
关键字,并用我的内核模块的名称replace了可执行文件的path:
probe perf.hw.cache_references.module(MODULE_NAME).counter("find_insns") {}
我很确定,我的模块有debugging信息,但运行我得到的脚本:
语义错误:parsing探测点:在perf.stp:14:7源标识符'perf':probe perf.hw.instructions.module(MODULE_NAME).counter(“find_insns”){}
任何想法可能是错的?
编辑:
好吧,我意识到perf计数器可能会被绑定到只处理模块(这里解释: https : //sourceware.org/systemtap/man/stapprobes.3stap.html )。 所以我把它改回到:
probe perf.hw.cache_references.process(PATH_TO_BINARY).counter("find_insns") {}
现在,如示例脚本所示,我有:
probe module(MODULE_NAME).function(FUNC_NAME) { #save counter values on entrance ... }
但现在运行它,我得到:
语义错误:perf计数器'find_insns'未定义语义错误:parsing探测点时:perf.stp:26:7处的标识符'module'source:探针模块(MODULE_NAME).function(FUNC_NAME)
EDIT2:
所以这是我的完整脚本:
#! /usr/bin/env stap # Usage: stap perf.stp <path-to-binary> <module-name> <function-name> global cycles_per_insn global branch_per_insn global cacheref_per_insn global insns global cycles global branches global cacherefs global insn global cachemisses global miss_per_insn probe perf.hw.instructions.process(@1).counter("find_insns") {} probe perf.hw.cpu_cycles.process(@1).counter("find_cycles") {} probe perf.hw.branch_instructions.process(@1).counter("find_branches") {} probe perf.hw.cache_references.process(@1).counter("find_cache_refs") {} probe perf.hw.cache_misses.process(@1).counter("find_cache_misses") {} probe module(@2).function(@3) { insn["find_insns"] = @perf("find_insns") insns <<< (insn["find_insns"]) insn["find_cycles"] = @perf("find_cycles") cycles <<< insn["find_cycles"] insn["find_branches"] = @perf("find_branches") branches <<< insn["find_branches"] insn["find_cache_refs"] = @perf("find_cache_refs") cacherefs <<< insn["find_cache_refs"] insn["find_cache_misses"] = @perf("find_cache_misses") cachemisses <<< insn["find_cache_misses"] } probe module(@2).function(@3).return { dividend = (@perf("find_cycles") - insn["find_cycles"]) divisor = (@perf("find_insns") - insn["find_insns"]) q = dividend / divisor if (q > 0) cycles_per_insn <<< q dividend = (@perf("find_branches") - insn["find_branches"]) q = dividend / divisor if (q > 0) branch_per_insn <<< q dividend = (@perf("find_cycles") - insn["find_cycles"]) q = dividend / divisor if (q > 0) cacheref_per_insn <<< q dividend = (@perf("find_cache_misses") - insn["find_cache_misses"]) q = dividend / divisor if (q > 0) miss_per_insn <<< q } probe end { if (@count(cycles_per_insn)) { printf ("Cycles per Insn\n\n") print (@hist_log(cycles_per_insn)) } if (@count(branch_per_insn)) { printf ("\nBranches per Insn\n\n") print (@hist_log(branch_per_insn)) } if (@count(cacheref_per_insn)) { printf ("Cache Refs per Insn\n\n") print (@hist_log(cacheref_per_insn)) } if (@count(miss_per_insn)) { printf ("Cache Misses per Insn\n\n") print (@hist_log(miss_per_insn)) } }
Systemtap无法读取内核探测器的硬件perfctr值,因为linux没有提供合适的(例如,原子的)内部API来安全地从所有上下文中读取这些值。 perf …过程探测器的工作原理只是因为该上下文不是原子的:systemtap探测器处理程序可以安全地进行阻塞。
我无法回答你关于上次试验过的两个(?)脚本的详细问题,因为它们不完整。