Python popenX() slowness on AIX?
allenjo5 at mail.northgrum.com
allenjo5 at mail.northgrum.com
Fri Nov 24 12:03:41 EST 2006
Stefaan A Eeckels wrote:
> On 21 Nov 2006 13:02:14 -0800
> allenjo5 at mail.northgrum.com wrote:
>
> > The fact that it does this in Python code instead of C is the main
> > cause of the slowness. So, unless Python is changed to do this in C,
> > it's always going to be slow on AIX :-(
>
> I guess that the reason it's slow is that there are many descriptors to
> try and close. Reducing them using ulimit -n could improve the speed.
>
> AIX has a fcntl command to close all open file descriptors from a
> descriptor onwards:
>
> fcntl(3, F_CLOSEM);
>
> This of course should be used instead of the loop:
>
> import sys
> import fcntl
>
> __all__ = ["popen2", "popen3", "popen4"]
>
> ...
>
> def _run_child(self, cmd):
> if isinstance(cmd, basestring):
> cmd = ['/bin/sh', '-c', cmd]
> try:
> os.fcntl(3, 10, 0)
> except OSError:
> pass
> try:
> os.execvp(cmd[0], cmd)
> finally:
> os._exit(1)
>
> 10 happens to be the value of F_CLOSEM (from /usr/include/fcntl.h).
> I've currently no access to an AIX system with Python, but it could be
> worth trying.
Yes, very much worth it. F_CLOSEM is _so_ much better than the loop,
even in C. Using your brilliant suggestion, I now have a simple patch
to the python source that implements it for any OS that happens to have
the fcntl F_CLOSEM option. It is below in its entirety. I believe I
got the try: stuff correct, but since I'm new to Python, I'd appreciate
any comments.
I have another patch to implement my os.rclose(x,y) method, which would
improve the speed of popenX() for the OSes that don't have F_CLOSEM, by
doing the close() loop in C instead of Python, but I don't know if it
would be as likely to be accepted as this probably would be.
Now, where do I send my proposed patch for consideration?
John.
--- ./Modules/fcntlmodule.c.orig Thu Jun 3 08:47:26 2004
+++ ./Modules/fcntlmodule.c Fri Nov 24 11:18:23 2006
@@ -545,6 +545,11 @@
if (ins(d, "DN_MULTISHOT", (long)DN_MULTISHOT)) return -1;
#endif
+/* For systems like AIX that have F_CLOSEM to close multiple fds */
+#ifdef F_CLOSEM
+ if (ins(d, "F_CLOSEM", (long)F_CLOSEM)) return -1;
+#endif
+
#ifdef HAVE_STROPTS_H
/* Unix 98 guarantees that these are in stropts.h. */
INS(I_PUSH);
--- ./Lib/popen2.py.orig Thu Feb 10 08:46:14 2005
+++ ./Lib/popen2.py Fri Nov 24 11:37:15 2006
@@ -8,6 +8,7 @@
import os
import sys
+import fcntl
__all__ = ["popen2", "popen3", "popen4"]
@@ -65,11 +66,18 @@
def _run_child(self, cmd):
if isinstance(cmd, basestring):
cmd = ['/bin/sh', '-c', cmd]
- for i in range(3, MAXFD):
- try:
- os.close(i)
- except OSError:
- pass
+ try:
+ if fcntl.F_CLOSEM:
+ try:
+ fcntl.fcntl(3, fcntl.F_CLOSEM, 0)
+ except OSError:
+ pass
+ except AttributeError:
+ for i in range(3, MAXFD):
+ try:
+ os.close(i)
+ except OSError:
+ pass
try:
os.execvp(cmd[0], cmd)
finally:
More information about the Python-list
mailing list