我意识到“快”有点主观,所以我会解释一些上下文。我正在开发一个名为psutil的Python模块,用于以跨平台的方式读取流程信息。其中一个函数是用于确定PID是否在当前进程列表中的pid_exists(pid)
函数。
现在,我以一种显而易见的方式来做这件事,使用EnumProcesses()来拉取进程列表,然后遍历列表并查找PID。但是,一些简单的基准测试表明,这比基于UNIX平台(Linux、OS X、FreeBSD)上的pid撸exists函数要慢得多,在这些平台上,我们使用带0信号的kill(pid, 0)
来确定pid是否存在。额外的测试显示,几乎所有的时间都在占用枚举进程。
有谁知道比使用枚举进程确定PID是否存在更快的方法吗?我试着OpenProcess()并检查打开不存在的进程时是否有错误,但这比遍历enumprocess列表慢了4倍多,所以这也算出来了。还有其他(更好的)建议吗?
注意:这是一个Python库,旨在避免pywin32扩展等第三方lib依赖项。我需要一个比我们当前代码更快的解决方案,它不依赖于pywin32或标准Python发行版中没有的其他模块。
编辑:为了澄清-我们很清楚阅读过程的形成有着固有的种族条件。如果在数据收集过程中进程消失或遇到其他问题,我们会引发异常。函数的作用不是要替换正确的错误处理。
更新:很明显,我以前的基准测试有缺陷——我用C编写了一些简单的测试应用程序,EnumProcesses总是输出得比较慢,而OpenProcess(如果PID有效但进程已停止,则与GetProcessExitCode一起)实际上要快得多,而不是慢得多。
后来的测试显示OpenProcess和GetExitCodeProcess毕竟比使用enumprocess快得多,结果发现我的基准显然有缺陷。我不确定发生了什么,但我做了一些新的测试,并验证了这是更快的解决方案:
注意,您确实需要使用
GetExitCodeProcess()
,因为OpenProcess()
将在最近死亡的进程上成功,因此您不能假定有效的进程句柄表示该进程正在运行。还要注意,
OpenProcess()
对于任何有效PID的3以内的PID都是成功的(请参见Why does OpenProcess succeed even when I add three to the process ID?)OpenProcess可能会告诉您不需要枚举所有内容。我不知道有多快。
编辑:请注意,您还需要
GetExitCodeProcess
来验证进程的状态,即使您从OpenProcess
获得了句柄。在使用pid_exists函数时存在一个固有的竞争条件:当调用程序使用应答时,进程可能已经消失,或者可能已经创建了一个具有查询id的新进程。我敢说,任何使用此功能的应用程序都存在设计缺陷,因此优化此功能是不值得的。
相关问题 更多 >
编程相关推荐