-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
bpo-29883: Add UDP support to Windows Proactor Event Loop #1067
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
Conversation
@ameily, thanks for your PR! By analyzing the history of the files in this pull request, we identified @1st1, @zooba and @birkenfeld to be potential reviewers. |
You might be able to remove some code by using If I'm reading this correctly, your I'm not sure what the best solution is. AFAICT libuv's solution is that it just keeps starting You might also find this interested as a general overview of the challenges of making IOCP work well: python-trio/trio#52 |
Oops, forgot to include this link to more discussion of the chromium thing: https://groups.google.com/a/chromium.org/forum/#!topic/net-dev/VTPH1D8M6Ds |
@njsmith Thanks for the feedback and resources.
I can take a look at
You are correct. I didn't want to run into the problem you described where we just spam the network with UDP packets. I can change it to only allow a certain number of outstanding
Yup, I've been testing on a real network. I wrote a simple script to query a network's Windows systems NetBIOS name, which operates over UDP. The loopback address is only used in the unit tests, which I modeled after the TCP unit tests where nothing is actually written to the network. I understand that IOCP UDP performance may not be the best but I think it's something that should be in the main CPython if possible. I need it on a project where I'm performing asynchronous TCP and UDP operations and the Selector event loop is adding a substantial amount of overhead (~80% in some cases). I can add a disclaimer in the documentation that IOCP sockets aren't the best option for high performance/traffic UDP applications. I'll also take a look at the resources you linked to see if there are other ways I can improve the implementation. |
I don't know. It's something I have been trying to figure out as well :-). Like I said, AFAICT from reading the source libuv doesn't appear to put any upper bound on the number of outstanding send operations, so maybe that works? There's even an argument that one should handle UDP by making non-blocking |
I've done some benchmarking to help determine the best design for high efficiency UDP over IOCP.
I was surprised that the synchronous design did not drop any packets and The benchmark script I wrote is here: https://gist.github.com/ameily/3b801a32b0c896a2c4791abcf56cc3e1. Each design I tested requires some modification of the core Python source code but I used the same script for each design. |
FYI, since this is a new feature, it's not eligible for a backport to 3.5, or even 3.6. New features can't go into any released version of Python. (unless Guido asks for it, which is rare) |
@larryhastings Yes, this will be a 3.7-only thing. |
@ameily Somehow I missed this PR :( Let's work on it and get it merged asap. Could you please rebase it against the current master? |
c979273
to
9fc145b
Compare
I've rebased onto upstream master. Now, one of the tests is timing out:
I've narrowed it down to a call to |
53ab614
to
ec3a18b
Compare
This PR is now rebased onto upstream master. |
Cool! |
@asvetlov from my perspective, yes, this PR is ready for review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made a couple of linter-style comments, but apart from the borrowed references, it looks pretty good to me.
@zooba I believe I addressed your feedback and made my changes PEP 7 compliant. |
@asvetlov Sorry, force of habit. I changed my calls to just be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing I'd like to fix in this PR is to remove mock tests completely and replace them with proper functional tests. Most of existing mock tests in asyncio will either be removed before 3.8 or replaced with proper functional tests.
Mock tests are tightly coupled with the implementation and prevent us from freely refactoring it. IMO It's better to have one or two functional tests than an array of mock tests.
I recommend you to take a the uvloop project and copy the UDP tests from there and maybe come up with a couple more, if needed.
@vstinner I believe I fixed the memory leak. I also rebased onto upstream/master.
|
Strange. I don't know why it leaks on my Windows VM. This PR has other flaws:
I have a WIP change on top of this PR, but I didn't have time to finish it yet :-( |
@vstinner could you provide a link to your WIP? I think we should be consistent.
|
@vstinner which function originates the leak? afaict |
@ameily looks like it failed some tests in
|
This PR adds UDP support to the Windows Proactor Event Loop. Several changes were performed:
WSAConnect
- ConnectEx doesn't support binding a UDP endpoint to a socket so I had to add this. WSAConnect completes immediately for UDP sockets.WSARecvFrom
WSASendTo
_make_datagram_transport()
and the corresponding UDP transport class_ProactorDatagramTransport
.WSARecv
andWSASend
. Unbound UDP endpoints require calls toWSARecvFrom
andWSASendTo
.I've verified that the change can be cleanly applied to master, 3.5, and 3.6. So, back porting this feature will be straightforward, which I would like personally since I require this feature on a Python 3.5 project.
One of the SSL unit tests is failing and I've verified that the same test fails with the same error in
master
.https://bugs.python.org/issue29883