linux - 每秒将“perf stat”输出保存到文件中
问题描述
我想获得性能输出并对其进行分析。我用了
while (true) {
system("sudo perf kvm stat -e r10f4 -a sleep 1 2>&1 | sed '1,3d' | sed '2,$d' > 'system.log' 2>&1");
sleep(0.5);
}
上面的代码经常使用 perf,代价高昂。相反,我正在运行 perf stat ,例如:perf kvm stat -a -I 1000 > system.log 2>&1
。
此命令将继续将数据写入“system.log”,但我只需要一秒钟内的数据。
我想知道如何让新数据每秒覆盖旧数据。有人知道我的想法是否可行吗?或其他可以解决我的问题的方法。
解决方案
你的意思是让 perf 继续覆盖,而不是追加,所以你只有最后一秒?
一种方法是让您自己的程序管道perf stat -I1000
进入自身(例如,通过 C stdiopopen
或使用 POSIX pipe
// dup2
fork/exec)。然后,您可以实现选择将行写入文件的位置和方式的逻辑。您可以在每次写入之前查找输出文件的开头,而不仅仅是正常写入它们。或者pwrite
不要write
总是在文件位置 0 处写入。您可以附加一些空格以填充到固定宽度,以确保较长的行不会在文件中留下一些您没有覆盖的字符。(或ftruncate
写入后的输出文件比前一行短)。
或者:perf stat -I 1000 >> file.log
使用 O_APPEND 重定向,并定期截断长度。
为追加而打开的文件将自动写入当前结尾的任何位置,因此您可以perf ... -I 1000
每秒或每 5 秒左右保持运行并截断文件。所以最多你有 5 行要通读,才能读到你真正想要的最后一行。如果system
用于通过 shell 运行它,请使用>>
. 或者使用open(O_APPEND)
/dup2
如果使用fork
/ execve
。
在循环中truncate()
通过路径或ftruncate()
打开 fd进行实际截断。sleep
理想情况下,您会在即将编写新行之前截断,因此大多数时候都会有一行。但是除非您进行额外的系统调用,fstat
否则inotify
您将不知道何时确切地期待另一个系统调用,尽管航位推算并假设 sleep 睡眠时间最短可以正常工作。
或者:重定向perf stat -I 1000
(不附加),并从父进程中查找它的 fd,以创建与通过在写入前查找的进程/线程进行管道相同的效果。
为什么分叉我的进程会导致文件被无限读取表明具有共享相同打开文件描述的文件描述符的父/子进程可以影响彼此的文件位置lseek
。
这仅在您使用open
/自己进行重定向时才有效dup2
,而不是在您通过system
. 您需要自己的描述符来引用相同的打开文件描述
不确定您是否可以lseek
在子进程打开的同一个 fd 上玩技巧;在这种情况下,避免 O_APPEND 可以让您将写入位置设置为 0 而不会截断,因此下一次写入将覆盖内容。但这仅在您open
///并且父进程中的 fd 的文件位置与子进程中的 fd 绑定时才有效dup2
。fork
exec
完全未经测试的例子
即使使用正确的标头,这实际上也可能无法编译,但希望能说明这个想法。
// must *not* use O_APPEND, otherwise file position is ignored for write.
int fd = open("system.log", O_WRONLY|O_CREAT|O_TRUNC, 0666);
if ((pid = fork()) != 0){
// parent
while(1) {
sleep(1);
lseek(fd, 0, SEEK_SET); // reset the position at which perf will do its next write
}
} else {
// child
dup2(fd, 1); // redirect stdout to the open file
// TODO: look up best practices for fork/exec, and error checking
execlp("sudo", "perf", "kvm", "stat", "-er10f4", "-a", "sleep", "1", NULL);
perror("execlp sudo perf failed");
}
请注意完全缺乏对返回值的错误检查。这更像是伪代码,即使它是用(希望)有效的 C 语法编写的。
顺便说一句,您可以将该管道减少为一个sed
命令,仅sed -n 4p
打印第 4 行而不是其他行。但是perf ... stat -I 1000
不会浪费行,因此无需以这种方式过滤行号。
推荐阅读
- mysql - 尝试将日期从 SQL Server 字符串转换为 MySQL DATE
- react-native - 错误:无法从“node_modules/react-navigation-tabs/src/navigators/createBottomTabNavigator.js”解析模块“react-native-screens”
- emscripten - Envoy 可以解释 wasm 还是 wasm 对它不透明?
- java - 类型参数 T 具有不兼容的上限视图和片段
- javascript - 如何从html文件中提取特定标题下的所有文本
- .net - 在 Dot net 错误页面和 IIS 错误页面中隐藏路径信息
- javascript - 在 d3.js 中的树图中显示节点内的文本
- ios - 为什么 SwiftUI 初始化程序调用不同?
- c++ - 如何从字符串 C++ 中读取多个整数
- css - React JS:如何根据另一个元素的className bgcolor样式更改一组div中div的bgcolor