[Python-checkins] peps: PEP 433: add test scripts; performances results on Linux 3.6

victor.stinner python-checkins at python.org
Mon Jan 28 16:17:29 CET 2013


http://hg.python.org/peps/rev/d269feb2c809
changeset:   4694:d269feb2c809
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Sun Jan 27 13:35:21 2013 +0100
summary:
  PEP 433: add test scripts; performances results on Linux 3.6

files:
  pep-0433.txt              |  15 ++++++--
  pep-0433/bench_cloexec.py |  45 +++++++++++++++++++++++++++
  pep-0433/openbsd_bug.py   |  32 +++++++++++++++++++
  3 files changed, 88 insertions(+), 4 deletions(-)


diff --git a/pep-0433.txt b/pep-0433.txt
--- a/pep-0433.txt
+++ b/pep-0433.txt
@@ -143,9 +143,8 @@
 .. note::
    OpenBSD older 5.2 does not close the file descriptor with
    close-on-exec flag set if ``fork()`` is used before ``exec()``, but
-   it works correctly if ``exec()`` is called without ``fork()``.
-
-XXX recheck this OpenBSD bug using a C program. XXX
+   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>`_.
 
 
 Scope
@@ -446,7 +445,15 @@
  * ``fcntl(fd, F_SETFD, flags)``: two addition system calls per file
    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
diff --git a/pep-0433/bench_cloexec.py b/pep-0433/bench_cloexec.py
new file mode 100644
--- /dev/null
+++ b/pep-0433/bench_cloexec.py
@@ -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))
diff --git a/pep-0433/openbsd_bug.py b/pep-0433/openbsd_bug.py
new file mode 100644
--- /dev/null
+++ b/pep-0433/openbsd_bug.py
@@ -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)

-- 
Repository URL: http://hg.python.org/peps


More information about the Python-checkins mailing list