Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance issue (+fix) AIX ctypes.util with no /sbin/ldconfig present #66025

Closed
twbert mannequin opened this issue Jun 22, 2014 · 8 comments
Closed

Performance issue (+fix) AIX ctypes.util with no /sbin/ldconfig present #66025

twbert mannequin opened this issue Jun 22, 2014 · 8 comments

Comments

@twbert
Copy link
Mannequin

twbert mannequin commented Jun 22, 2014

BPO 21826
Nosy @bitdancer, @vadmium, @aixtools
Files
  • patch_ctypes_util_py.diff
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2018-07-23.06:55:39.453>
    created_at = <Date 2014-06-22.16:01:11.222>
    labels = ['ctypes']
    title = 'Performance issue (+fix) AIX ctypes.util with no /sbin/ldconfig present'
    updated_at = <Date 2018-07-23.06:55:39.453>
    user = 'https://bugs.python.org/twbert'

    bugs.python.org fields:

    activity = <Date 2018-07-23.06:55:39.453>
    actor = 'berker.peksag'
    assignee = 'none'
    closed = True
    closed_date = <Date 2018-07-23.06:55:39.453>
    closer = 'berker.peksag'
    components = ['ctypes']
    creation = <Date 2014-06-22.16:01:11.222>
    creator = 'tw.bert'
    dependencies = []
    files = ['35726']
    hgrepos = []
    issue_num = 21826
    keywords = ['patch']
    message_count = 8.0
    messages = ['221266', '221278', '221284', '264149', '273324', '273539', '274901', '322181']
    nosy_count = 4.0
    nosy_names = ['r.david.murray', 'martin.panter', 'tw.bert', 'Michael.Felt']
    pr_nums = []
    priority = 'normal'
    resolution = 'wont fix'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue21826'
    versions = ['Python 2.7']

    @twbert
    Copy link
    Mannequin Author

    twbert mannequin commented Jun 22, 2014

    Preample: This is my first post to the python issue tracker, I included a fix.

    This issue is probably related to http://bugs.python.org/issue11063 .

    The problem:

    After upgrading a package on AIX 7.1 x64 that started using the uuid module, we experienced serious performance issues.

    The culprit (found after a day of debugging) is here:

    File: ctypes/util.py
    Note: The file /sbin/ldconfig does *not* exist, so no useful information is collected here.
    The statement:

    f = os.popen('/sbin/ldconfig -p 2>/dev/null')

    To be more specific about the performace at popen(), the performance degradation happens in it's close() method. It takes 300 ms, which is unacceptable. In a larger scope, statements that took 200ms now take 1400ms (because the above is called several times.

    If I simply check for os.path.exists before the popen, the performance is fine again. See the included simple patch. It's a simple unix diff, we don't have git on that machine. Git can handle those diffs easily to my knowledge.

    More information:

    Small scope, culprit identified:

    import os, time, traceback
    print os.__file__
    print time.clock(),'pre'
    f = None
    try:
      #if os.path.exists('/sbin/ldconfig'):
      f = os.popen('/sbin/ldconfig -p 2>/dev/null')
    except:
      print traceback.format_exc()
    finally:
      print time.clock(),'post close'
      if f: f.close()
      print time.clock(),'post finally'

    This takes 300ms (post finally) without the check for exists.

    Large scope, before patch:
    time python -c "import hiredis;import redis;print 'redis-py version: %s , hiredis-py version: %s' %(redis.VERSION,hiredis.__ver
    sion__,)"
    redis-py version: (2, 10, 1) , hiredis-py version: 0.1.3

    real 0m1.409s
    user 0m0.416s
    sys 0m0.129s

    Large scope, after patch:
    time python -c "import hiredis;import redis;print 'redis-py version: %s , hiredis-py version: %s' %(redis.VERSION,hiredis.__ver
    sion__,)"
    redis-py version: (2, 10, 1) , hiredis-py version: 0.1.3

    real 0m0.192s
    user 0m0.056s
    sys 0m0.050s

    @twbert twbert mannequin added the topic-ctypes label Jun 22, 2014
    @bitdancer
    Copy link
    Member

    How does this interact with bpo-11063?

    @twbert
    Copy link
    Mannequin Author

    twbert mannequin commented Jun 22, 2014

    Hi David, thank you for looking into this.
    bpo-11063 starts with "When the uuid.py module is simply imported it has the side effect of forking a subprocess (/sbin/ldconfig) and doing a lot of stuff find a uuid implementation by ctypes.".

    My fix is specific about solving the AIX performance problem I encounter in the exact same condition as above. My guess is, that if 11063 is picked up (not using external tools), the AIX performance problem will be addressed automatically, rendering the new bpo-21826 obsolete.

    @vadmium
    Copy link
    Member

    vadmium commented Apr 25, 2016

    See also bpo-26439 about find_library() AIX support

    @vadmium
    Copy link
    Member

    vadmium commented Aug 22, 2016

    It looks like Bert’s patch adjusted two ldconfig calls; the first one was in a BSD-specific branch. Was this intended? Only the second call (default “else:” branch) seems applicable to AIX.

    Perhaps the performance is improved now that the popen() shell calls have been replaced with more direct subprocess.Popen() calls; see revision a09ae70f3489 and bpo-22636. If the 300 ms slowdown was due to the shell, that should no longer be a problem.

    But if the slowdown is say inherent in fork(), I am not sure it is worth adding the proposed os.path.exists() check. Either try a way of spawning a child process without fork(), like bpo-20104. Or avoid calling find_library() in the first place, like I suggested at <https://bugs.python.org/issue11063#msg264151\>.

    @vadmium
    Copy link
    Member

    vadmium commented Aug 24, 2016

    For the record, if you wanted to actually load the library function on AIX, I understand the code might look a bit like:

    if sys.platform.startswith("aix"):
        if sys.maxsize > 2**32:
            lib = "libc.a(shr_64.o)"
        else:
            lib = "libc.a(shr.o)"
        RTLD_MEMBER = 0x00040000
        lib = ctypes.CDLL(lib, ctypes.DEFAULT_MODE | RTLD_MEMBER)
        _uuid_generate_time = lib.uuid_generate_time
    else:
        # The uuid_generate_* routines are provided by libuuid on at least
        # Linux and FreeBSD, and provided by libc on Mac OS X.
        ...

    @aixtools
    Copy link
    Contributor

    aixtools commented Sep 7, 2016

    re: bpo-26439 and bpo-27435 would like to show:

    without patch, find_library() is consistently slow, and in default situations, returns nothing.

    root@x064:[/data/prj/aixtools/python/python-2.7.10]./python -m timeit -n 100 'import ctypes.util; ctypes.util.find_library("crypt")'
    100 loops, best of 3: 29.6 msec per loop
    root@x064:[/data/prj/aixtools/python/python-2.7.10]./python -m timeit -n 100 'import ctypes.util; ctypes.util.find_library("crypt")'
    100 loops, best of 3: 28.8 msec per loop
    root@x064:[/data/prj/aixtools/python/python-2.7.10]./python -m timeit -n 100 'import ctypes.util; ctypes.util.find_library("c")'
    100 loops, best of 3: 29.4 msec per loop
    root@x064:[/data/prj/aixtools/python/python-2.7.10]./python -m timeit -n 100 'import ctypes.util; ctypes.util.find_library("m")'
    100 loops, best of 3: 29.8 msec per loop
    root@x064:[/data/prj/aixtools/python/python-2.7.10]cd -
    /data/prj/aixtools/python/python-2.7.12.1
    root@x064:[/data/prj/aixtools/python/python-2.7.12.1]./python -m timeit -n 100 'import ctypes.util; ctypes.util.find_library("crypt")'
    100 loops, best of 3: 13.5 msec per loop
    root@x064:[/data/prj/aixtools/python/python-2.7.12.1]./python -m timeit -n 100 'import ctypes.util; ctypes.util.find_library("c")'
    100 loops, best of 3: 21.4 msec per loop
    root@x064:[/data/prj/aixtools/python/python-2.7.12.1]./python -m timeit -n 100 'import ctypes.util; ctypes.util.find_library("m")'
    100 loops, best of 3: 26.1 msec per loop

    The results can be explained as follows:
    no patch - all fail, nothing is ever found in a default environment.

    with patch: crypt - the answer includes the archive member libcrypt.so, so it is found "earlier" than for "c" which must look for legacy names, which is faster than "m" which does not exist.

    What I consider "frightening" - and a good reason to stay with Python2 as long as possible is the follow difference
    Python3.6a2 - unpatched, versus Python3.6a4 - ctypes.util patched for AIX:

    root@x064:[/data/prj/aixtools/python/python-3.6.0.162]./python -m timeit -n 100 'import ctypes.util; ctypes.util.find_library("crypt")'
    100 loops, best of 3: 84.1 msec per loop
    root@x064:[/data/prj/aixtools/python/python-3.6.0.162]cd ../*164
    root@x064:[/data/prj/aixtools/python/python-3.6.0.164]./python -m timeit -n 100 'import ctypes.util; ctypes.util.find_library("crypt")'
    100 loops, best of 3: 66.6 msec per loop

    FYI: this is on a POWER6 (so h/w is 'quite old', msec should be seen as relative, not as accurate for newer hardware)

    @aixtools
    Copy link
    Contributor

    as this is fixed is Python3.7 (see bpo-26439) and has been stated several times that it will not be fixed in Python2.7 I suspect this issue may also be closed.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    No branches or pull requests

    4 participants