c - 为什么 ls 的这些指令计数差异如此之大?(ptrace vs perf vs qemu)
问题描述
我想计算运行 /bin/ls 时执行的指令总数。我使用了 3 种结果差异很大的方法,我不知道为什么。
1. 使用 ptrace 进行指令计数
我编写了一段代码,它调用 ls 的一个实例并使用 ptrace 单步执行它:
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/user.h>
#include <sys/reg.h>
#include <sys/syscall.h>
int main()
{
pid_t child;
child = fork(); //create child
if(child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
char* child_argv[] = {"/bin/ls", NULL};
execv("/bin/ls", child_argv);
}
else {
int status;
long long ins_count = 0;
while(1)
{
//stop tracing if child terminated successfully
wait(&status);
if(WIFEXITED(status))
break;
ins_count++;
ptrace(PTRACE_SINGLESTEP, child, NULL, NULL);
}
printf("\n%lld Instructions executed.\n", ins_count);
}
return 0;
}
运行这段代码给了我 516.678 条指令。
2.QEMU单步
我在单步模式下使用 qemu 模拟 ls 并使用以下命令将所有传入指令记录到日志文件中: qemu-x86_64 -singlestep -D logfile -d in_asm /bin/ls
根据 qemuls 执行 16.836 条指令。
3.性能
须藤性能统计
这个命令给了我 8.162.180 条指令执行。
我知道这些指令中的大多数来自动态链接器,它们被计算在内很好。但为什么这些数字相差如此之大?他们不应该都一样吗?
解决方案
为什么这些指令计数差异如此之大?因为他们真正衡量的东西不同,只有衡量的单位是一样的。就好像你在称你从商店里拿来的东西,一个人称所有的东西都没有包装,甚至没有贴纸,另一个人称它在包装中,也包括购物袋,还有一个人还加了你带来的泥土。房子在你的靴子上。
这几乎就是这里发生的事情:指令计数不仅仅是ls
二进制文件中的指令计数,还可以包括它使用的库、引入这些库所需的内核加载器的服务,以及最后执行的代码在进程中,但在内核上下文中。在这方面,您使用的方法都表现不同。所以问题是:你需要从那个测量中得到什么?如果你需要“总的努力”,那么最大的肯定就是你想要的:这将包括内核造成的一些开销。如果您需要“我只想知道发生了什么ls
”,那么最小的数字就是您想要的。
推荐阅读
- javascript - 如何在单页应用程序 (SPA) 中正确配置 Firebase 身份验证?
- java - 如何配置 jhipster 应用程序
- javascript - NuxtJS:如果 id 未定义或为空,则禁用链接
- python - NameError:名称“win”未使用 tkinter python 定义
- fastapi - 使用快速 api 读取 json:api 过滤器
- android - 同时循环两个列表,同时在每个步骤比较和存储每个循环的结果
- java - 了解迭代器
- python - AWS Lambda - 无法导入模块 lambda-function
- javascript - React.js:未捕获(承诺)SyntaxError:JSON输入意外结束
- c - 指针转换的奇怪结果