Skip to content

gh-72894: Dynamically allocate select fd_sets on Windows based on inputs size #13842

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

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

andzn
Copy link

@andzn andzn commented Jun 5, 2019

@andzn andzn changed the title bpo-28708: Raise FD_SETSIZE limit to 16384 bpo-28708: Raise FD_SETSIZE limit to 16384 on windows Jun 5, 2019
@asvetlov
Copy link
Contributor

asvetlov commented Jun 5, 2019

By this PR you basically increased the memory consumption for every select call from 12 KiB to 384 KiB.
I believe the number is too high.

See the issue's comment added recently

@andzn andzn changed the title bpo-28708: Raise FD_SETSIZE limit to 16384 on windows bpo-28708: Dynamically allocate select fd_sets on Windows based on inputs size Jun 10, 2019
Copy link
Contributor

@jdemeyer jdemeyer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To test the new seqsize() code path, I would like to see a test added where select.select() is called with an iterable which is not a tuple or list, for example iter([fd]) instead of [fd].

Copy link
Contributor

@jdemeyer jdemeyer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are also missing error checks where you call seqsize().

@bedevere-bot
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

And if you don't make the requested changes, you will be put in the comfy chair!

@andzn
Copy link
Author

andzn commented Jun 14, 2019

I have made the requested changes; please review again

@bedevere-bot
Copy link

Thanks for making the requested changes!

@asvetlov: please review the changes made to this pull request.

@andzn
Copy link
Author

andzn commented Jun 14, 2019

@jdmeyer I removed the seqsize function completely and replaced calls with PySequence_Length.

@NewUserHa
Copy link
Contributor

NewUserHa commented Jun 15, 2019

hope this pass soon.
select() limit really is pain ass.

@csabella csabella requested review from jdemeyer and asvetlov January 25, 2020 20:16
@csabella
Copy link
Contributor

@andzn, please resolve the merge conflict. Thank you!

@andzn
Copy link
Author

andzn commented Jan 27, 2020

@csabella , merge conflicts are now resolved.

@andzn
Copy link
Author

andzn commented Jul 28, 2020

@asvetlov, @jdemeyer can you please take a look again at the PR? The requested changes have already been implemented a year ago.

@arhadthedev arhadthedev changed the title bpo-28708: Dynamically allocate select fd_sets on Windows based on inputs size gh-72894: Dynamically allocate select fd_sets on Windows based on inputs size Feb 17, 2023
@arhadthedev arhadthedev added performance Performance or resource usage OS-windows extension-modules C modules in the Modules dir topic-IO labels Feb 17, 2023
@arhadthedev
Copy link
Member

@andzn Could you sign the new CLA by clicking not signed button in the cpython-cla-bot's message, please?

@andzn
Copy link
Author

andzn commented Feb 17, 2023

@andzn Could you sign the new CLA by clicking not signed button in the cpython-cla-bot's message, please?

@arhadthedev done.

do {
if (((fd_set FAR *)(set))->fd_count < setsize)
((fd_set FAR *)(set))->fd_array[((fd_set FAR *)(set))->fd_count++]=(fd);
} while(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of the surrounding code do { ... } while (0)?

Comment on lines +123 to +124
size_t i;
for (i = 0; i < setsize + 1 && fd2obj[i].sentinel >= 0; i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
size_t i;
for (i = 0; i < setsize + 1 && fd2obj[i].sentinel >= 0; i++) {
for (size_t i = 0; i < setsize + 1 && fd2obj[i].sentinel >= 0; i++) {

@@ -196,7 +211,7 @@ set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1])
return NULL;

i = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you declare i here?

struct timeval tv, *tvp;
int imax, omax, emax, max;
int n;
_PyTime_t timeout, deadline = 0;

setsize = FD_SETSIZE;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to initialize the variable where it's declared. Either declare it at this line, or move the declaration here. So the variable is never uninitialized.

return NULL;
}

if ((size_t)rsize > setsize) setsize = (size_t)rsize;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may write: setsize = Py_MAX(setsize, (size_t)rsize); (same for the 2 lines below). IMO it's more explicit (and how I would write it in Python).

ofdset = (fd_set*) PyMem_NEW(SOCKET, setsize + 1);
efdset = (fd_set*) PyMem_NEW(SOCKET, setsize + 1);
if (ifdset->fd_array == NULL || ofdset->fd_array == NULL || efdset->fd_array == NULL) {
if (ifdset->fd_array) PyMem_DEL(ifdset->fd_array);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PyMem_DEL() is a alias to PyMem_Free(): use it directly.

The NULL test is useless and can be removed. PyMem_Free(NULL) is well defined, it does nothing: https://docs.python.org/dev/c-api/memory.html#c.PyMem_Free

fd_set *ifdset, *ofdset, *efdset;
#if !defined(MS_WINDOWS)
fd_set ifdset_stack, ofdset_stack, efdset_stack;
#if !defined(SELECT_USES_HEAP)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would make the code simpler if the SELECT_USES_HEAP macro would always be defined on Windows, no?

@python python deleted a comment Apr 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting change review extension-modules C modules in the Modules dir OS-windows performance Performance or resource usage topic-IO
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants