【问题标题】:Measuring user+system runtime of external program测量外部程序的用户+系统运行时间
【发布时间】:2015-03-10 08:01:42
【问题描述】:

作为评估的一部分,我想测量和比较不同差异工具的用户+系统运行时间。 作为第一种方法,我考虑使用 time - f (GNU time) 调用特定工具。由于其余的评估是由一堆 Python 脚本完成的,所以我想用 Python 来实现它。

时间输出格式如下:

<some error message>
user 0.4
sys 0.2

diff 工具的输出被重定向到sed 以去除不需要的输出,然后进一步处理sed 的输出。 (在我的示例中不推荐使用sed。参见编辑2)

shell 中的调用如下所示(删除以“Binary”开头的行):

$ time -f "user %U\nsys %S\n" diff -r -u0 dirA dirB | sed -e '/^Binary.*/d'

到目前为止,这是我的方法:

import subprocess

diffcommand=["time","-f","user %U\nsys %S\n","diff","-r","-u0","testrepo_1/A/rev","testrepo_1/B/rev"]
sedcommand = ["sed","-e","/^Binary.*/d"]

# Execute command as subprocess
diff = subprocess.Popen(diffcommand, stderr=subprocess.PIPE, stdout=subprocess.PIPE)

# Calculate runtime
runtime = 0.0
for line in diff.stderr.readlines():
    current = line.split()
    if current:
        if current[0] == "user" or current[0] == "sys":
            runtime = runtime + float(current[1])
print "Runtime: "+str(runtime)

# Pipe to "sed"
sedresult = subprocess.check_output(sedcommand, stdin=diff.stdout)

 # Wait for the subprocesses to terminate
diff.wait()

但是感觉这并不干净(尤其是从操作系统的角度来看)。在某些我还无法弄清楚的情况下,它还会导致脚本卡在readlines 部分。

是否有更清洁(或更好)的方式来实现我想要的?

编辑 1 换了标题,给出了更详细的解释

编辑 2 感谢 J.F. Sebastian,我查看了 os.wait4(...)(信息取自 his answer。但由于我对输出感兴趣,我必须实现它有点不同。

我的代码现在看起来像这样:

diffprocess = subprocess.Popen(diffcommand,stdout=subprocess.PIPE)
runtimes = os.wait4(diffprocess.pid,0)[2]
runtime = runtimes.ru_utime + runtimes.ru_stime
diffresult = diffprocess.communicate()[0]

请注意,我不再将结果通过管道传递给sed(决定在python中进行修剪)

运行时测量对于某些测试用例工作正常,但有时执行会卡住。然后删除运行时测量有助于程序终止,发送stdoutDEVNULL(根据here 的要求)也是如此。我可以陷入僵局吗? (valgrind --tool=helgrind 没有找到任何东西)我的方法有什么根本错误吗?

【问题讨论】:

  • 试试timeit
  • 你知道difflibfilecmp吗?
  • @LutzHorn:由于我对“真实”运行时感兴趣(无需等待时间段等),我认为这可能不够准确。
  • @PeterWood:是的,但我正在测量不同差异工具在特定情况下的运行时间。以上是我编写的整个评估框架的一部分
  • 您的评估框架正在使用从 Python 调用的 GNU 时间?

标签: python subprocess stderr


【解决方案1】:

但执行有时会卡住。

如果您使用stdout=PIPE,那么 something 应该在进程仍在运行时读取输出 否则如果子进程的 stdout OS 管道缓冲区已满,子进程将挂起(在我的机器上约为 65K)。

from subprocess import Popen, PIPE

p = Popen(diffcommand, stdout=PIPE, bufsize=-1)
with p.stdout:
    output = p.stdout.read()
ru = os.wait4(p.pid, 0)[2]

【讨论】:

  • 我也想过同样的问题,但不知道如何解决。非常适合我:-)....但是你能解释一下bufsize 参数的作用吗?
  • @Paddre: bufsize 作为管道的the buffering parameter while creating file objects 传递。在 Python 2 上,bufsize=0 可能会对性能产生负面影响。在 Python 3(最新版本)上,默认值等同于 bufsize=-1。默认情况下,存在带有bufsize=0 的中间 Python 3 版本,这可能会导致 Python 3 上的短读取(错误结果)。
猜你喜欢
  • 2013-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-10
相关资源
最近更新 更多