[issue18932] Optimize selectors.EpollSelector.modify()

STINNER Victor report at bugs.python.org
Wed Feb 4 21:25:57 CET 2015


STINNER Victor added the comment:

Benchmark on Fedora 21 (Linux 3.18.3, glibc 2.20, Python 3.5 rev 7494f3972726).

Original:

haypo at selma$ ./python -m timeit -s 'import os, selectors; s=selectors.SelectSelector(); r,w=os.pipe(); s.register(r, selectors.EVENT_READ)' 's.modify(r, selectors.EVENT_WRITE); s.modify(r, selectors.EVENT_READ)'
10000 loops, best of 3: 43.7 usec per loop
haypo at selma$ ./python -m timeit -s 'import os, selectors; s=selectors.PollSelector(); r,w=os.pipe(); s.register(r, selectors.EVENT_READ)' 's.modify(r, selectors.EVENT_WRITE); s.modify(r, selectors.EVENT_READ)'
10000 loops, best of 3: 45.1 usec per loop
haypo at selma$ ./python -m timeit -s 'import os, selectors; s=selectors.EpollSelector(); r,w=os.pipe(); s.register(r, selectors.EVENT_READ)' 's.modify(r, selectors.EVENT_WRITE); s.modify(r, selectors.EVENT_READ)'
10000 loops, best of 3: 48.4 usec per loop

Patched:

haypo at selma$ ./python -m timeit -s 'import os, selectors; s=selectors.SelectSelector(); r,w=os.pipe(); s.register(r, selectors.EVENT_READ)' 's.modify(r, selectors.EVENT_WRITE); s.modify(r, selectors.EVENT_READ)'
10000 loops, best of 3: 37.2 usec per loop
haypo at selma$ ./python -m timeit -s 'import os, selectors; s=selectors.PollSelector(); r,w=os.pipe(); s.register(r, selectors.EVENT_READ)' 's.modify(r, selectors.EVENT_WRITE); s.modify(r, selectors.EVENT_READ)'
10000 loops, best of 3: 40.5 usec per loop
haypo at selma$ ./python -m timeit -s 'import os, selectors; s=selectors.EpollSelector(); r,w=os.pipe(); s.register(r, selectors.EVENT_READ)' 's.modify(r, selectors.EVENT_WRITE); s.modify(r, selectors.EVENT_READ)'
10000 loops, best of 3: 39.9 usec per loop

* SelectSelector: 14% faster (-6.5 us)
* PollSelector: 10% faster (-4.6 us)
* EpollSelector: 18% faster (-8.5 us)

--

> _BaseSelectorImpl.modify() still calls unregister() and register().

I chose to factorize code in modify() and only put the specific code in _modify(). The advantage is to pass directly oldkey and key to _modify().

We may even try to keep the selector consistent if _modify() fails. For example, start with unregister, and only register if _modify() succeed.

--

In a previous (local) patch, the default implementation of _modify() was:

    self.unregister(fileobj)
    return self.register(fileobj, events, data)

And each specialized _modify() started with:

    oldkey = self.unregister(fileobj)
    key = self.register(fileobj, events, data)

Do you prefer this?

----------

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue18932>
_______________________________________


More information about the Python-bugs-list mailing list