在一个处理器中使用python内置探查器和脚本runninng(并且没有多线程)
time python -m cProfile myscript.py
分析器报告的CPU时间为345.710 CPU秒
24184348 function calls (24183732 primitive calls) in 345.710 CPU seconds
和真实的,用户和 sys 时间是:
real 5m45.926s
user 1m59.340s
sys 0m39.452s
正如您所看到的,CPU时间几乎是实时(345.710 = 5m45.710s)。
因此,考虑到结果,是否可以假设分析器报告的CPU时间包括其他进程使用的时间片以及进程花费的时间?即,探查器CPU时间不是处理时间(用户+系统),而是如下所述的挂钟时间 What do 'real', 'user' and 'sys' mean in the output of time(1)?
非常感谢提前
答案 0 :(得分:13)
This answers关于真实,用户和系统时间含义的精美细节。引用:
'Real'是挂钟时间 - 从通话开始到结束的时间。这个 是所有经过的时间,包括其他进程使用的时间片和 进程花费的时间被阻止(例如,如果它正在等待I / O. 完成)。
'用户'是用户模式代码中花费的CPU时间(在...之外) 内核)在这个过程中。这只是实际使用的CPU时间 执行过程。流程花费的其他流程和时间 被阻止不计入这个数字。
'Sys'是进程内核中花费的CPU时间。 这意味着执行在系统调用中花费的CPU时间 内核,而不是仍在运行的库代码 用户空间。与“用户”一样,这只是流程使用的CPU时间。
从上面的解释看,User + Sys时间应该等于CPU秒。相反,它更接近'真实'时间。奇怪!
对此有一个公平的解释。 “用户”时间不包括在进程内的I / O操作上花费的CPU秒数。它只测量在内存中花费在用户模式代码上的CPU时间。经验法则是:
实时=用户+ sys + I / O时间+解释器启动时间+字节码编译时间
为了验证这一点,我进行了urllib2.urlopen(urllib2.Request(url))
调用,进行密集的I / O.结果如下:
100792 function calls (98867 primitive calls) in 2.076 CPU seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
512 0.719 0.001 0.719 0.001 {method 'recv' of '_socket.socket' objects}
1 0.464 0.464 0.473 0.473 {_socket.getaddrinfo}
1 0.352 0.352 0.352 0.352 <string>:1(connect)
1 0.248 0.248 0.348 0.348 common_functions.py:1(<module>)
1 0.022 0.022 0.075 0.075 __init__.py:2(<module>)
1 0.017 0.017 0.030 0.030 urllib.py:1442(getproxies_macosx_sysconf)
330/67 0.012 0.000 0.031 0.000 sre_parse.py:385(_parse)
real 0m2.255s
user 0m0.352s
sys 0m0.093s
此处,I / O操作(主要是_socket.socket
和_socket.getaddrinfo
)消耗了2.076-(0.352 + 0.093),即1.631 CPU秒。其余的时间,2.255-2.076,用于冷启动代码。
希望这很有用。
更新:在多个核心系统中,多个CPU并行工作,情况略有不同。 cProfile报告的总CPU秒数是所有CPU单独花费的时间总和。例如:在2核系统中,如果一个CPU工作10秒。同时,另一个CPU工作15秒。报告的总CPU秒数为25秒。虽然实际流逝的时间可能只有15秒。因此,在多核系统中, CPU时间可能超过实时。由于CPU正在并行工作
答案 1 :(得分:7)
我对同样的问题感到困惑。
答案是cProfile使用挂钟时间。它的输出在历史上是错误的,但现在已经修复('CPU秒'中的'CPU'已被删除)。我不确切知道什么时候,但Debian 6.0中的Python 2.6.6有bug,而Debian 7.0中的Python 2.7.3则没问题。
这很令人费解,因为大多数分析器会占用CPU上的时间,而不是占用时钟。但这是一个“廉价”的探测器。
文档http://docs.python.org/2/library/profile.html#limitations解释 - 不清楚 - 时间是基于滴答作响的挂钟,而不是getrusage()或ptrace技术。
如果您检查代码(http://hg.python.org/cpython/file/44f455e6163d/Modules/_lsprof.c),则可以验证它是否为QueryPerformanceFrequency / gettimeofday。
Jerrymouse关于“时间”和cProfile时间不能重合的事实是正确的,因为cProfile只在代码编译后才开始运行。但除此之外,它的“实时”方程式也是假的。
wallclock和user + sys之间的区别可能在于许多不同的因素,例如代表您的进程的I / O或代表任何其他进程(包括内核本身(交换,日记等))或CPU时间花在其他进程上,或代表您的进程等待任何无法计算的进程,因为它是远程资源(网络,或通过NFS或iSCSI间接),等等。您可以命名。
答案 2 :(得分:6)
Python分析器默认测量墙上时间,但可以使用自定义计时器功能测量CPU时间。以下工作在Linux下工作,但不适用于Windows(因为time.clock
测量Windows上的挂起时间):
import cProfile
import time
def idleWait():
time.sleep(10)
def busyWait():
t = time.time() + 10
while time.time() < t: pass
def target():
idleWait()
busyWait()
print "Wall time:"
p = cProfile.Profile()
p.runcall(target)
p.print_stats()
print "CPU time:"
p = cProfile.Profile(time.clock)
p.runcall(target)
p.print_stats()
第一次配置文件运行将显示20秒,其中约一半用于time.sleep
。第二个显示已过去10秒,其中没有一个花费在time.sleep
。