问题在于:有一组用不同语言(主要是 Perl 和 Python)编写的程序。每个节目x
从 stdin
读取行, 做一些工作(解析行,更新数据结构,不需要长时间查询 DB 或花哨的网络通信,甚至磁盘 IO 也很少见),并且可能会打印一些东西到 stdout
.任务是编写这样的程序f
,即给定 x
和 stdin
, 将对此类行进行采样,这对于 x
而言在计算上是最困难的。 .这个想法是使用这样的行来测试和基准测试 x
在 future 。
这是我陷入困境的事情:f
包裹 x
, 读取一行 l
来自 stdin
, x
准备处理 l
, f
通行证l
至 x
并立即开始收集有关 x
的统计信息.问题是我找不到任何可以区分计算难度和简单线条的指标。目前我已经尝试了两种方法:
/proc/[x pid]/stat
在 x
的运行之间.它几乎不会改变(甚至 CPU 滴答声)。 x
状态(使用相同的 /proc/[x pid]/stat
)并尝试测量它运行的时间。行之间没有区别。 也许有一些高精度指标?比如运行的 CPU 命令数量或使用的内存中的字节数?
这是我用 Python 编写的实际代码,它充满了细节,所以我认为这是最后一件事 https://gist.github.com/alexanderkuk/5630079#file-f-py .
最佳答案
你的代码有很多问题。首先,这个:
def command_is_running(pid):
with open('/proc/%d/stat' % pid) as stat:
stats = stat.read()
return ' R ' in stats
def wait_command_processes_line(pid):
# stats = ...
while command_is_running(pid):
# stats = update_stats(stats, pid)
return stats
是一个繁忙的循环。它会吃掉尽可能多的 CPU,阅读
.../stat
反复直到R
消失了。当您试图获得准确的 CPU 使用时间时,运行额外的 CPU 占用进程不是一个好主意。我不知道有什么方法可以让一个进程进入休眠状态,直到另一个进程的运行状态发生变化,所以我不能提供一个有效的替代繁忙循环的方法。但这并不重要,因为第二个问题:进程状态不像您希望的那样可预测。
您已经假设该进程将在您将一些数据写入其管道的那一刻变得可运行,并且将在处理该输入的持续时间内保持可运行状态。很难保证这是真的。您已经说过“磁盘 IO 很少见”,但您必须做得更好并完全消除它,包括页面错误。这很难,你可能还没有做到。所以我认为你的问题不是
/proc/PID/stat
包含错误的信息,但您在错误的时间阅读它。您可以通过处理
D
来解决磁盘 IO 问题。状态与 R
相同.但它看起来仍然很笨拙。与其查看进程的可运行性,不如找到一个更好的指标,表明子进程已完成处理最近的输入行。你说它“可能会打印一些东西到标准输出”。如果您可以安排它始终为每个输入行打印一些内容到标准输出,那么父进程可以等待该输出并在它出现时对子进程的 CPU 使用情况进行采样。
如果您不能让子进程为每个输入行提供完成的外部指示,另一种方法可能是在它尝试读取下一个输入行时考虑使用输入行完成。基本上你会使用
ptrace
实现专门的 strace
-like实用程序,记录read
的次数s 在输入管道上,只有在您的跟踪告诉您它正在尝试读取后才将一行写入管道。也许你甚至可以用
strace
做到这一点和一些巧妙的 shell 脚本。该想法的另一个变体是使用
gdb
在其输入处理循环开始时在子进程中设置断点,并设置每次命中断点时运行的脚本。该脚本将收集计时信息,将下一行写入管道,然后执行 gdb cont
.
关于unix - 有没有办法获得有关 Unix 进程的非常精确的信息(使用的字节数、CPU 指令数)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16700096/