- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用posix_spawn而不是fork/exec来获得一些性能提升。我当前的项目是用Python编写的,所以我使用了this Python 绑定(bind)。我还尝试了它的一些分支,之后我在 Cython 中编写了自己的 posix_spawn 绑定(bind)(以摆脱一些依赖项),但获得了几乎相同的结果。
当我只需要运行进程而不捕获 stdout/stderr 时,确实有显着的加速。但是当我确实需要它时(对于我的项目来说这是必要的),posix_spawn 调用变得与 fork/exec 调用一样慢。此外,它与 fork/exec 一样取决于分配的内存量。即使该过程实际上没有产生任何输出,它也会发生 - 我检查了/bin/true。我仍然无法解释这种行为。对于 fork/exec(通过 subprocess 模块),只要输出不是太大,无论我们是否读取进程输出,都没有显着差异。
这是我的测试脚本(省略了导入和分析代码)
# test.py
def spawn_no_out(args):
command = args[0]
pid = posix_spawn(command, args)
status, rusage = exits(pid)
def spawn(args):
# Prepare pipes to capture stdout and stderr
stdout_read, stdout_write = os.pipe()
stderr_read, stderr_write = os.pipe()
fa = FileActions()
fa.add_dup2(stdout_write, 1)
fa.add_close(stdout_read)
fa.add_dup2(stderr_write, 2)
fa.add_close(stderr_read)
# Spawn the process
command = args[0]
pid = posix_spawn(command, args, file_actions=fa)
# Read and close file descriptors
os.close(stdout_write)
os.close(stderr_write)
status, rusage = exits(pid)
out = os.fdopen(stdout_read)
err = os.fdopen(stderr_read)
return out, err
def fork(args):
return Popen(args, stdout=PIPE, stderr=PIPE).communicate()
def fork_no_out(args):
return subprocess.call(args)
def run_benchmark(func, args, count):
for _ in xrange(count):
func(args)
print "%s: %ds" % (func.__name__, time.time() - start)
def main():
# Reads from stdout the number of process spawns and size of allocated memory
args = ["/bin/true"]
count = int(sys.argv[1]) if len(sys.argv) > 1 else 1000
mem_size = int(sys.argv[2]) if len(sys.argv) > 2 else 10000000
some_allocated_memory = range(mem_size)
for func in [spawn, spawn_no_out, fork, fork_no_out]:
run_benchmark(func, args, count)
if __name__ == "__main__":
main()
在不分配额外内存的情况下测试输出:
./test.py 10000 1spawn: 34s 3754834 function calls (3754776 primitive calls) in 33.517 seconds Ordered by: internal time, cumulative time List reduced from 144 to 5 due to restriction ncalls tottime percall cumtime percall filename:lineno(function) 10000 15.475 0.002 15.475 0.002 {posix.wait4} 10000 5.850 0.001 5.850 0.001 {_cffi__x2c5d2681xf492c09f.posix_spawn} 10000 3.217 0.000 12.750 0.001 /usr/local/lib/python2.7/dist-packages/posix_spawn-0.1-py2.7.egg/posix_spawn/_impl.py:75(posix_spawn) 10000 2.242 0.000 33.280 0.003 ./test.py:23(spawn) 660000 1.777 0.000 3.159 0.000 /usr/local/lib/python2.7/dist-packages/cffi/api.py:212(new)spawn_no_out: 14s 3340013 function calls in 14.631 seconds Ordered by: internal time, cumulative time List reduced from 25 to 5 due to restriction ncalls tottime percall cumtime percall filename:lineno(function) 10000 7.466 0.001 7.466 0.001 {posix.wait4} 10000 2.012 0.000 2.012 0.000 {_cffi__x2c5d2681xf492c09f.posix_spawn} 10000 1.658 0.000 6.994 0.001 /usr/local/lib/python2.7/dist-packages/posix_spawn-0.1-py2.7.egg/posix_spawn/_impl.py:75(posix_spawn) 650000 1.640 0.000 2.919 0.000 /usr/local/lib/python2.7/dist-packages/cffi/api.py:212(new) 650000 0.496 0.000 0.496 0.000 {_cffi_backend.newp}fork: 40s 840094 function calls in 40.745 seconds Ordered by: internal time, cumulative time List reduced from 53 to 5 due to restriction ncalls tottime percall cumtime percall filename:lineno(function) 10000 19.460 0.002 19.460 0.002 {posix.read} 10000 6.505 0.001 6.505 0.001 {posix.fork} 10081 4.667 0.000 4.667 0.000 {built-in method poll} 10000 2.773 0.000 30.190 0.003 /usr/lib/python2.7/subprocess.py:1187(_execute_child) 10000 0.814 0.000 32.996 0.003 /usr/lib/python2.7/subprocess.py:650(__init__)fork_no_out: 38s 330013 function calls in 38.488 seconds Ordered by: internal time, cumulative time List reduced from 36 to 5 due to restriction ncalls tottime percall cumtime percall filename:lineno(function) 10000 18.179 0.002 18.179 0.002 {posix.read} 10000 6.904 0.001 6.904 0.001 {posix.waitpid} 10000 6.613 0.001 6.613 0.001 {posix.fork} 10000 2.633 0.000 28.976 0.003 /usr/lib/python2.7/subprocess.py:1187(_execute_child) 10000 0.880 0.000 30.070 0.003 /usr/lib/python2.7/subprocess.py:650(__init__)
Test output with allocated memory for list of 10000000 integers (had to decrease the number of calls):
./test.py 1000 10000000spawn: 20s 379834 function calls (379776 primitive calls) in 20.022 seconds Ordered by: internal time, cumulative time List reduced from 144 to 5 due to restriction ncalls tottime percall cumtime percall filename:lineno(function) 1000 10.022 0.010 10.022 0.010 {posix.wait4} 1000 8.705 0.009 8.705 0.009 {_cffi__x2c5d2681xf492c09f.posix_spawn} 1000 0.334 0.000 9.412 0.009 /usr/local/lib/python2.7/dist-packages/posix_spawn-0.1-py2.7.egg/posix_spawn/_impl.py:75(posix_spawn) 1000 0.269 0.000 19.998 0.020 ./test.py:18(spawn) 66000 0.174 0.000 0.318 0.000 /usr/local/lib/python2.7/dist-packages/cffi/api.py:212(new)spawn_no_out: 1s 334013 function calls in 1.480 seconds Ordered by: internal time, cumulative time List reduced from 25 to 5 due to restriction ncalls tottime percall cumtime percall filename:lineno(function) 1000 0.755 0.001 0.755 0.001 {posix.wait4} 1000 0.198 0.000 0.198 0.000 {_cffi__x2c5d2681xf492c09f.posix_spawn} 1000 0.171 0.000 0.708 0.001 /usr/local/lib/python2.7/dist-packages/posix_spawn-0.1-py2.7.egg/posix_spawn/_impl.py:75(posix_spawn) 65000 0.167 0.000 0.298 0.000 /usr/local/lib/python2.7/dist-packages/cffi/api.py:212(new) 65000 0.050 0.000 0.050 0.000 {_cffi_backend.newp}fork: 18s 84067 function calls in 18.554 seconds Ordered by: internal time, cumulative time List reduced from 53 to 5 due to restriction ncalls tottime percall cumtime percall filename:lineno(function) 1000 9.399 0.009 9.399 0.009 {posix.read} 1000 7.815 0.008 7.815 0.008 {posix.fork} 1054 0.414 0.000 0.414 0.000 {built-in method poll} 1000 0.274 0.000 17.626 0.018 /usr/lib/python2.7/subprocess.py:1187(_execute_child) 1000 0.078 0.000 17.871 0.018 /usr/lib/python2.7/subprocess.py:650(__init__)fork_no_out: 18s 33013 function calls in 18.732 seconds Ordered by: internal time, cumulative time List reduced from 36 to 5 due to restriction ncalls tottime percall cumtime percall filename:lineno(function) 1000 9.467 0.009 9.467 0.009 {posix.read} 1000 8.020 0.008 8.020 0.008 {posix.fork} 1000 0.603 0.001 0.603 0.001 {posix.waitpid} 1000 0.280 0.000 17.910 0.018 /usr/lib/python2.7/subprocess.py:1187(_execute_child) 1000 0.072 0.000 18.000 0.018 /usr/lib/python2.7/subprocess.py:650(__init__)
Without profiling the results are the same.As we can see, there is a huge difference (1.4s vs 20s!) in performance for the cases when we call posix_spawn with and without capturing process output. There is no additional heavy calls - posix.wait4 just takes more time.What could I have done wrong here? Does someone have an idea why it happens and how to get better performance for posix_spawn?
P.S. Tested on Linux Mint 17 and CentOS 6.5 - same results.
UPDATE:The same performance degradation happens even if we pass empty FileActions object to posix_spawn, without actually reading stdout/stderr:
def spawn(args):
command = args[0]
pid = posix_spawn(command, args, file_actions=FileActions())
status, rusage = exits(pid)
最佳答案
好吧,对于后代 - 似乎如果设置了 file_actions 并且未设置某些标志,posix_spawn 仅使用 fork: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/spawni.c;h=2d3ae941dd19f0348ed95c0b957c68c3c0e9815d;hb=c758a6861537815c759cba2018a3b1abb1943842#l97
关于python - 捕获进程输出时的 Posix_spawn 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33570947/
我正在处理一组标记为 160 个组的 173k 点。我想通过合并最接近的(到 9 或 10 个组)来减少组/集群的数量。我搜索过 sklearn 或类似的库,但没有成功。 我猜它只是通过 knn 聚类
我有一个扁平数字列表,这些数字逻辑上以 3 为一组,其中每个三元组是 (number, __ignored, flag[0 or 1]),例如: [7,56,1, 8,0,0, 2,0,0, 6,1,
我正在使用 pipenv 来管理我的包。我想编写一个 python 脚本来调用另一个使用不同虚拟环境(VE)的 python 脚本。 如何运行使用 VE1 的 python 脚本 1 并调用另一个 p
假设我有一个文件 script.py 位于 path = "foo/bar/script.py"。我正在寻找一种在 Python 中通过函数 execute_script() 从我的主要 Python
这听起来像是谜语或笑话,但实际上我还没有找到这个问题的答案。 问题到底是什么? 我想运行 2 个脚本。在第一个脚本中,我调用另一个脚本,但我希望它们继续并行,而不是在两个单独的线程中。主要是我不希望第
我有一个带有 python 2.5.5 的软件。我想发送一个命令,该命令将在 python 2.7.5 中启动一个脚本,然后继续执行该脚本。 我试过用 #!python2.7.5 和http://re
我在 python 命令行(使用 python 2.7)中,并尝试运行 Python 脚本。我的操作系统是 Windows 7。我已将我的目录设置为包含我所有脚本的文件夹,使用: os.chdir("
剧透:部分解决(见最后)。 以下是使用 Python 嵌入的代码示例: #include int main(int argc, char** argv) { Py_SetPythonHome
假设我有以下列表,对应于及时的股票价格: prices = [1, 3, 7, 10, 9, 8, 5, 3, 6, 8, 12, 9, 6, 10, 13, 8, 4, 11] 我想确定以下总体上最
所以我试图在选择某个单选按钮时更改此框架的背景。 我的框架位于一个类中,并且单选按钮的功能位于该类之外。 (这样我就可以在所有其他框架上调用它们。) 问题是每当我选择单选按钮时都会出现以下错误: co
我正在尝试将字符串与 python 中的正则表达式进行比较,如下所示, #!/usr/bin/env python3 import re str1 = "Expecting property name
考虑以下原型(prototype) Boost.Python 模块,该模块从单独的 C++ 头文件中引入类“D”。 /* file: a/b.cpp */ BOOST_PYTHON_MODULE(c)
如何编写一个程序来“识别函数调用的行号?” python 检查模块提供了定位行号的选项,但是, def di(): return inspect.currentframe().f_back.f_l
我已经使用 macports 安装了 Python 2.7,并且由于我的 $PATH 变量,这就是我输入 $ python 时得到的变量。然而,virtualenv 默认使用 Python 2.6,除
我只想问如何加快 python 上的 re.search 速度。 我有一个很长的字符串行,长度为 176861(即带有一些符号的字母数字字符),我使用此函数测试了该行以进行研究: def getExe
list1= [u'%app%%General%%Council%', u'%people%', u'%people%%Regional%%Council%%Mandate%', u'%ppp%%Ge
这个问题在这里已经有了答案: Is it Pythonic to use list comprehensions for just side effects? (7 个答案) 关闭 4 个月前。 告
我想用 Python 将两个列表组合成一个列表,方法如下: a = [1,1,1,2,2,2,3,3,3,3] b= ["Sun", "is", "bright", "June","and" ,"Ju
我正在运行带有最新 Boost 发行版 (1.55.0) 的 Mac OS X 10.8.4 (Darwin 12.4.0)。我正在按照说明 here构建包含在我的发行版中的教程 Boost-Pyth
学习 Python,我正在尝试制作一个没有任何第 3 方库的网络抓取工具,这样过程对我来说并没有简化,而且我知道我在做什么。我浏览了一些在线资源,但所有这些都让我对某些事情感到困惑。 html 看起来
我是一名优秀的程序员,十分优秀!