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

Switch internal agent selector to improve throughput #17

Closed
sagebind opened this issue Jan 18, 2019 · 2 comments · Fixed by #243
Closed

Switch internal agent selector to improve throughput #17

sagebind opened this issue Jan 18, 2019 · 2 comments · Fixed by #243
Assignees
Labels
performance An enhancement or problem with performance windows Windows-specific issue

Comments

@sagebind
Copy link
Owner

sagebind commented Jan 18, 2019

libcurl uses poll(2) at best case for its selector implementation, and at worst case uses select(2), which can perform rather badly with many concurrent requests. Isahc already performs really well (at least under unix-like systems), but to get maximum possible performance, we should switch away from using curl_multi_select() and switch to using a library that efficiently uses the best selector available on the target system. This should especially aid performance on Windows, where IOCP has far better throughput than select(2).

Initially we investigated using Mio which has many nice benefits, but unfortunately will not work for us since Mio requires ownership of the socket handles and requires all read and write calls to go through Mio. But libcurl is going to read and write to the socket handles directly and we can't change that, so Mio is out.

Sometime after this issue was initially created the polling crate was introduced, which looks very promising and should work for us as an alternative. It has less features than Mio, but frankly we don't need those extra features, and more importantly polling allows us to keep ownership of the socket handles. On Windows it uses wepoll which is a widely accepted readiness-driven wrapper around IOCP that performs well.

Implementation is slow-going, but is on this PR here: #243

@sagebind sagebind self-assigned this Jan 18, 2019
@sagebind sagebind added the performance An enhancement or problem with performance label Jan 18, 2019
@sagebind
Copy link
Owner Author

sagebind commented May 14, 2019

It appears that this cannot be done on Windows without modifying libcurl to make less assumptions with its socket management. Closing this for now, as it isn't worth the high effort for an unknown amount of efficiency improvement.

In particular, IOCP on Windows requires you to use specific read and write functions instead of the standard ones, which libcurl doesn't allow you to configure.

@sagebind sagebind reopened this Oct 23, 2020
@sagebind sagebind added the windows Windows-specific issue label Oct 23, 2020
@sagebind sagebind changed the title Switch internal agent selector to Mio Switch internal agent selector to improve throughput Oct 23, 2020
@sagebind
Copy link
Owner Author

Re-opened, since we finally have a potential way forward using the excellent polling crate.

sagebind added a commit that referenced this issue Oct 24, 2020
sagebind added a commit that referenced this issue Feb 22, 2021
Replace the built-in `select(2)`-based I/O driver with [polling](https://github.com/stjepang/polling), which should deliver noticeably better throughput under high activity, _especially_ on Windows.

Fixes #17.
sagebind added a commit that referenced this issue Mar 10, 2021
Replace the built-in `select(2)`-based I/O driver with [polling](https://github.com/stjepang/polling), which should deliver noticeably better throughput under high activity, _especially_ on Windows.

This implementation took several attempts before I fully understood some of the curl quirks on how it handles sockets; for example, curl will often close sockets before asking them to be de-registered, register and deregister the same file descriptor number between polls (because the OS reused the number), and request sockets to be registered before they are initialized. To handle these quirks this provides a wrapper layer around the polling crate that translates this behavior into something polling can handle.

In addition to verifying all the tests pass, I've also run a sort of "soak test" on Linux, Windows, and macOS for 12 hours straight that makes many requests repeatedly in order to weed out potential random errors (I learned of the possible Win32 error code `ERROR_NOT_FOUND (0x490)` this way!).

Fixes #17.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance An enhancement or problem with performance windows Windows-specific issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant