execv() 贵吗?
Is execv() expensive?
我有一个要求。我的进程必须在其代码路径之一期间 fork->exec 另一个进程。子进程运行一些检查,当某些条件为真时,它必须重新执行自身。当我在高端机器上测试时,它没有引起任何性能问题。
但是在同一个进程中再次调用 execv() 会很昂贵吗?特别是当它自己执行时?
注意:第二次没有涉及到fork()。该进程将第二次执行 execv() 本身,以在其虚拟地址 space.
中重新映射某些内容
第二次 execv()
电话并不比第一次贵。它甚至可能更便宜,因为系统可能不需要从磁盘读取程序映像,并且不需要加载任何新的动态库。
另一方面,execv()
只是在同一个程序中进行分支,成本要高得多。我无法想象我想编写一个程序来重新执行自身(不分叉)而不是仅仅调用一个函数的情况。
另一方面,"cheap"和"expensive"是相对的。除非您经常这样做,否则您实际上可能不会注意到任何差异。
execve
系统调用有点贵; 运行 它每秒超过几十次 - 或者可能是几百次 - 是不合理的(即使它可能持续几毫秒,并且在大多数情况下可能持续几分之一毫秒)。
它可能比您将用来 近 模仿它的对 mmap(2) (& munmap
& mprotect(2)) and setcontext(3) 的十几个等效调用更快(更干净)(然后,有在执行 execve
的线程之外杀死 运行ning 线程的问题,以及附加到进程的其他资源,例如 FD_CLOEXEC
-ed 文件描述符)。
(您将无法用 mmap
、munmap
、setcontext
、close
复制 execve
正在做,但你可能已经足够接近了……但这太荒谬了)
此外,execve
的 实用 成本还应考虑共享库的动态加载量(应在 运行ning 之前加载main
,但技术上 在 execve
系统调用之后...)及其启动。
这个问题可能意义不大,它在很大程度上取决于机器的实际状态和 execve
ed executabe。我猜想 execve
一个巨大的 ELF 二进制文件(一些可执行文件可能有一个千兆字节的代码段,例如,传言说神秘的 Google 爬虫可能是一个具有十亿个 C++ 源代码行的整体程序,并且在有些时候它是静态链接的),例如有数百个共享库比 execve
长得多-在通常的 /bin/sh
.
我还猜想 execve
来自具有 TB 大小地址的进程 space 比通常的 execve
my zsh
shell 长得多正在我的桌面上做。
execve
它自己的程序(实际上是它的一些更新版本)的一个典型原因是,在一个持久的服务器中,当服务器的二进制可执行文件被更新时。
另一个 execve
它自己的程序的原因是有一个或多或少的 "stateless" 服务器(一些静态内容的网络服务器)重新启动并重新加载它的配置文件。
更一般地说,这是一个完整的研究课题:阅读有关 dynamic software updating, application checkpointing, persistence, etc... See also the references here。
在RAM中转储core(5) file: in my life, I never saw a core dump lasting more that a fraction of a second, but I did hear than on early 1990-s Cray computers, a core
dump could (pathologically) last half an hour.... So I imagine that some pathological execve
could last quite a long time (e.g. bringing a terabyte of code segment, using C-O-W技术是一样的;这不算 execve
时间,但它是启动程序成本的一部分;并且您还可能对许多共享库进行多次重定位。)。
附录
对于小型可执行文件(小于几兆字节),您可能负担得起每秒数百 execve
,因此这在实践中并不是什么大问题。请注意,带有 ls
、mv
等常用命令的 shell 脚本... execve
-ing 相当多(通常在一些 fork
之后)它几乎对每个命令都这样做)。如果您怀疑某些问题,您可以进行基准测试(例如 strace(1) using strace -tt -T -f
....). On my desktop Debian/x86-64/Sid i7 3770K an execve
of /bin/ls
(by strace --T -f -tt zsh-static -c ls
) takes about 250 µs (for an ELF binary executable /bin/ls
of 118Kbytes which is probably already in the page cache), and for ocamlc
(a binary of 1.8Mbyte) about 1.3ms ; a malloc
usually takes half or a few µs ; a call to time(2) takes about 3ns (avoiding the overhead of a syscall thru vdso(7)...)
我有一个要求。我的进程必须在其代码路径之一期间 fork->exec 另一个进程。子进程运行一些检查,当某些条件为真时,它必须重新执行自身。当我在高端机器上测试时,它没有引起任何性能问题。
但是在同一个进程中再次调用 execv() 会很昂贵吗?特别是当它自己执行时?
注意:第二次没有涉及到fork()。该进程将第二次执行 execv() 本身,以在其虚拟地址 space.
中重新映射某些内容第二次 execv()
电话并不比第一次贵。它甚至可能更便宜,因为系统可能不需要从磁盘读取程序映像,并且不需要加载任何新的动态库。
另一方面,execv()
只是在同一个程序中进行分支,成本要高得多。我无法想象我想编写一个程序来重新执行自身(不分叉)而不是仅仅调用一个函数的情况。
另一方面,"cheap"和"expensive"是相对的。除非您经常这样做,否则您实际上可能不会注意到任何差异。
execve
系统调用有点贵; 运行 它每秒超过几十次 - 或者可能是几百次 - 是不合理的(即使它可能持续几毫秒,并且在大多数情况下可能持续几分之一毫秒)。
它可能比您将用来 近 模仿它的对 mmap(2) (& munmap
& mprotect(2)) and setcontext(3) 的十几个等效调用更快(更干净)(然后,有在执行 execve
的线程之外杀死 运行ning 线程的问题,以及附加到进程的其他资源,例如 FD_CLOEXEC
-ed 文件描述符)。
(您将无法用 mmap
、munmap
、setcontext
、close
复制 execve
正在做,但你可能已经足够接近了……但这太荒谬了)
此外,execve
的 实用 成本还应考虑共享库的动态加载量(应在 运行ning 之前加载main
,但技术上 在 execve
系统调用之后...)及其启动。
这个问题可能意义不大,它在很大程度上取决于机器的实际状态和 execve
ed executabe。我猜想 execve
一个巨大的 ELF 二进制文件(一些可执行文件可能有一个千兆字节的代码段,例如,传言说神秘的 Google 爬虫可能是一个具有十亿个 C++ 源代码行的整体程序,并且在有些时候它是静态链接的),例如有数百个共享库比 execve
长得多-在通常的 /bin/sh
.
我还猜想 execve
来自具有 TB 大小地址的进程 space 比通常的 execve
my zsh
shell 长得多正在我的桌面上做。
execve
它自己的程序(实际上是它的一些更新版本)的一个典型原因是,在一个持久的服务器中,当服务器的二进制可执行文件被更新时。
另一个 execve
它自己的程序的原因是有一个或多或少的 "stateless" 服务器(一些静态内容的网络服务器)重新启动并重新加载它的配置文件。
更一般地说,这是一个完整的研究课题:阅读有关 dynamic software updating, application checkpointing, persistence, etc... See also the references here。
在RAM中转储core(5) file: in my life, I never saw a core dump lasting more that a fraction of a second, but I did hear than on early 1990-s Cray computers, a core
dump could (pathologically) last half an hour.... So I imagine that some pathological execve
could last quite a long time (e.g. bringing a terabyte of code segment, using C-O-W技术是一样的;这不算 execve
时间,但它是启动程序成本的一部分;并且您还可能对许多共享库进行多次重定位。)。
附录
对于小型可执行文件(小于几兆字节),您可能负担得起每秒数百 execve
,因此这在实践中并不是什么大问题。请注意,带有 ls
、mv
等常用命令的 shell 脚本... execve
-ing 相当多(通常在一些 fork
之后)它几乎对每个命令都这样做)。如果您怀疑某些问题,您可以进行基准测试(例如 strace(1) using strace -tt -T -f
....). On my desktop Debian/x86-64/Sid i7 3770K an execve
of /bin/ls
(by strace --T -f -tt zsh-static -c ls
) takes about 250 µs (for an ELF binary executable /bin/ls
of 118Kbytes which is probably already in the page cache), and for ocamlc
(a binary of 1.8Mbyte) about 1.3ms ; a malloc
usually takes half or a few µs ; a call to time(2) takes about 3ns (avoiding the overhead of a syscall thru vdso(7)...)