PEP 433: add test scripts; performances results on Linux 3.6

This commit is contained in:
Victor Stinner 2013-01-27 13:35:21 +01:00
parent d5f14bd374
commit 74a6f4b364
3 changed files with 88 additions and 4 deletions

View File

@ -143,9 +143,8 @@ the kernel ignores ``O_CLOEXEC`` or ``SOCK_CLOEXEC`` flag, a call to
.. note:: .. note::
OpenBSD older 5.2 does not close the file descriptor with OpenBSD older 5.2 does not close the file descriptor with
close-on-exec flag set if ``fork()`` is used before ``exec()``, but close-on-exec flag set if ``fork()`` is used before ``exec()``, but
it works correctly if ``exec()`` is called without ``fork()``. it works correctly if ``exec()`` is called without ``fork()``. Try
`openbsd_bug.py <http://hg.python.org/peps/file/tip/pep-0433/openbsd_bug.py>`_.
XXX recheck this OpenBSD bug using a C program. XXX
Scope Scope
@ -446,7 +445,15 @@ calls depends on the method used to set the flag:
* ``fcntl(fd, F_SETFD, flags)``: two addition system calls per file * ``fcntl(fd, F_SETFD, flags)``: two addition system calls per file
descriptor, one to get old flags and one to set new flags descriptor, one to get old flags and one to set new flags
XXX Benchmark the overhead for these 4 methods. XXX On Linux, setting the close-on-flag has a low overhead on performances.
Results of
`bench_cloexec.py <http://hg.python.org/peps/file/tip/pep-0433/bench_cloexec.py>`_
on Linux 3.6:
* close-on-flag not set: 7.8 us
* ``O_CLOEXEC``: 1% slower (7.9 us)
* ``ioctl()``: 3% slower (8.0 us)
* ``fcntl()``: 3% slower (8.0 us)
Implementation Implementation

45
pep-0433/bench_cloexec.py Normal file
View File

@ -0,0 +1,45 @@
"""
Linux 3.6, O_CLOEXEC:
open(cloexec=False) + close(): 7.76 us per call
open(cloexec=True) + close(): 7.87 us per call
=> 1% slower
Linux 3.6, ioctl(FIOCLEX):
open(cloexec=False) + close(): 7.77 us per call
open(cloexec=True) + close(): 8.02 us per call
=> 3% slower
Linux 3.6, fnctl(F_GETFD) + fnctl(F_SETFD):
open(cloexec=False) + close(): 7.77 us per call
open(cloexec=True) + close(): 8.01 us per call
=> 3% slower
"""
import os, time
name = __file__
LOOPS = 10**5
RUNS = 5
for cloexec in (False, True):
best = None
for run in range(RUNS):
print("cloexec", cloexec, "run", run)
time.sleep(1)
start = time.perf_counter()
for loops in range(LOOPS):
fd = os.open(name, os.O_RDONLY, cloexec=cloexec)
os.close(fd)
dt = time.perf_counter() - start
if best is not None:
best = min(best, dt)
else:
best = dt
seconds = best / LOOPS
print("open(cloexec=%s) + close(): %.2f us per call" % (cloexec, seconds * 1e6))

32
pep-0433/openbsd_bug.py Normal file
View File

@ -0,0 +1,32 @@
# Script testing an OpenBSD bug
#
# The script fails with "OS BUG!!!" with OpenBSD older than 5.2.
# It works on any version using USE_FORK = False.
USE_FORK = True
import fcntl, os, sys
fd = os.open("/etc/passwd", os.O_RDONLY)
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
flags |= fcntl.FD_CLOEXEC
fcntl.fcntl(fd, fcntl.F_SETFD, flags)
code = """
import os, sys
fd = int(sys.argv[1])
try:
os.fstat(fd)
except OSError:
print("fd %s closed by exec (FD_CLOEXEC works)" % fd)
else:
print("fd %s not closed by exec: FD_CLOEXEC doesn't work, OS BUG!!!" % fd)
"""
args = [sys.executable, '-c', code, str(fd)]
if USE_FORK:
pid = os.fork()
if pid:
os.waitpid(pid, 0)
sys.exit(0)
os.execv(args[0], args)