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
selector.EpollSelector: add new parameter to support EPOLLEXCLUSIVE #79698
Comments
Add a keyword argument for selector.EpollSelector with default value. This can help people use the EPOLLEXCLUSIVE since Python 3.7 and Linux Kernel 4.5 to avoid the herd effect like this def register(self, fileobj, events, data=None, exclusive=False):
key = super().register(fileobj, events, data)
epoll_events = 0
if events & EVENT_READ:
epoll_events |= select.EPOLLIN
if events & EVENT_WRITE:
epoll_events |= select.EPOLLOUT
try:
if exclusive and hasattr(select, "EPOLLEXCLUSIVE"):
epoll_events |= select.EPOLLEXCLUSIVE
self._epoll.register(key.fd, epoll_events)
except BaseException:
super().unregister(fileobj)
raise
return key |
I suggest to use a keyword-only parameter: def register(self, fileobj, events, data=None, *, exclusive=False): Do you want to work on a pull request? |
EPOLLEXCLUSIVE doc from Linux manual page: """ Sets an exclusive wakeup mode for the epoll file descriptor that If the same file descriptor is in multiple epoll instances, some The following values may be specified in conjunction with See also https://lwn.net/Articles/633422/ |
if exclusive and hasattr(select, "EPOLLEXCLUSIVE"):
epoll_events |= select.EPOLLEXCLUSIVE Maybe NotImplementedError would be more appropriate rather than silently ignore the error? |
I will work on a PR |
"a keyword-only parameter" is good I'll take it done |
I'm not sure I understand what EPOLLEXCLUSIVE is about. Could you provide a use case? Also, there are other constants which may also be useful such as EPOLLWAKEUP and EPOLLONESHOT:
That raises the question whether we should also have an "extra_events" argument for modify() method (probably yes). But again, I think it makes sense to understand what's the use case of these constants first, because if they are rarely used maybe who needs them can simply look at the source and use s._selector.modify() directly. |
Hello rodola Here's detail: In the server, we use multiprocess to handle the request with share the same FD. OK, when a request comes, all the process wake up and try to accept the request but only one process will accept success and the others will raise an Exception if we use the epoll without EPOLLEXCLUSIVE. That means there will waste the performance. This effect is named thundering herd. But if we use epoll with EPOLLEXCLUSIVE, when the envents happen, only one process will wake and try to handle the event. So, I think it's necessary to support the EPOLLEXCLUSIVE in selectors.EpollSelector Actually, Python support EPOLLEXCLUSIVE official since 3.7. It's time to support it in selectors |
I see. Then I would say it's a matter of deciding what's the best API to provide. Another possibility is to promote the underlying epoll() instance as a public property, so one can do:
That raises the question whether all selector classes should have a public "selector" attribute. poll() and devpoll() related classes may need it for POLLPRI, POLLRDHUP, POLLWRBAND or others (whatever their use case is). kqueue() also has it's own specific constants (KQ_FILTER_* and KQ_EV_*). The only one where a public "selector" property would be useless is SelectSelector. |
In my opinion selectors is an abstract for select, so I don't think allow people use select.* in selector is a good idea. like this
Because the multiple epoll's params are supported in different Python version and Linux Kernel version. So, I think it's a good idea to support different epoll's params by keyword-only param in register method. It's also convenient to check the params |
I prefer Giampaolo since discussed flags are very specific to epoll(): select() doesn't support them for example, nor kqueue nor devpoll (not *yet*). If we add a keyword-parameter, to me, it sounds like it's something "portable" working on multiple platforms and then you need hasattr(): if exclusive and hasattr(select, "EPOLLEXCLUSIVE"):
epoll_events |= select.EPOLLEXCLUSIVE If the caller pass select.EPOLLEXCLUSIVE, hasattr() is useless. Moreover, we directly support any EPOLL constant exposed in the select module. No need to change the API. |
OK, I will change my code |
Vicor:
I don't think so In class _PollLikeSelector ,here's register method def register(self, fileobj, events, data=None):
key = super().register(fileobj, events, data)
poller_events = 0
if events & EVENT_READ:
poller_events |= self._EVENT_READ
if events & EVENT_WRITE:
poller_events |= self._EVENT_WRITE this code filter the event that people push in it. It only supports select.EPOLLIN and select.EPOLLOUT |
I mean that using extra_events to get access to EPOLLEXCLUSIVE, there is no need later to add a new parameter for select.EPOLLONESHOT: it would be "future proof"! |
I took a look at your PR. As the PR currently stands it only works with epoll() selector. For the other selectors this is just an extra argument which does nothing, so it complicates the API of 2 methods for no real gain. Also, a single argument is not compatible with kqueue() because kqueue() requires two distinct Instead, I think simply turning the underlying selector instance into a public property is more flexible and less complex. On Linux you'll do:
Alternatively we could just keep |
Actually, in my implementation, it also supports POLL with the different event. I don't think to make selector be a public property is a good idea. It will break the whole system integrity. Please think about it, if people want to use epoll/poll with some special event, they must use it like this.
Here's a question, why we support the register? I think it will make people don't care about the detail. So, as you say, it's a little bit complicated, but it will help people don't care about the selector property detail, they just use the argument when they want to use it. I think it's worth it. |
Hmm, I forgot kqueue usage details: it operated not only with int flags but more complex structures. Please let me sleep on it. |
If exposing a private property is not a good idea, another choice may be construct a selector with a customized I/O multiplexer, adding an optional parameter to the __init__. But actually I'm -1 to this change. |
I agree with this.
I don't think so. If I use the So, why not change this API when we can keep the compatibility? |
ping.... |
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:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: