Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-92352 optimize Condition.notify()#92364

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed

Conversation

@dgiger42
Copy link
Contributor

@dgiger42dgiger42 commentedMay 6, 2022
edited
Loading

Closes#92352

This speeds upCondition.notify(). I benchmarked it with this command:
./python -m timeit -s 'import queue; q = queue.Queue()' 'for i in range(10 ** 6): q.put(42)'

Here are the timings with and without this PR:

1 loop, best of 5: 1.93 sec per loop  # original version1 loop, best of 5: 1.37 sec per loop  # with this PR

With this change,notify() no longer creates a new_deque every time. I think the speedup tends to be most noticeable when there aren't any threads waiting.

@ghost
Copy link

ghost commentedMay 6, 2022
edited by ghost
Loading

All commit authors signed the Contributor License Agreement.
CLA signed

@bedevere-bot
Copy link

Every change to Pythonrequires a NEWS entry.

Please, add it using theblurb_it Web app or theblurb command-line tool.

ifnotself._is_owned():
raiseRuntimeError("cannot notify on un-acquired lock")
all_waiters=self._waiters
waiters_to_notify=_deque(_islice(all_waiters,n))
Copy link
Member

Choose a reason for hiding this comment

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

After removingwaiters_to_notify,all_waiters looks bit ugly.
Please renameall_waiters to justwaiters.

forwaiterinwaiters_to_notify:
num_to_notify=min(n,len(waiters))
foriinrange(num_to_notify):
waiter=waiters.popleft()
Copy link
Contributor

@hauntsaninjahauntsaninjaMay 7, 2022
edited
Loading

Choose a reason for hiding this comment

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

The try-except in the old code aroundall_waiters.remove concerns me slightly, since it implies thatself._waiters can racily lose elements.

Maybe we should guard against waiters being emptyif not waiters: break or catchIndexError?

Copy link
Member

Choose a reason for hiding this comment

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

I think waiters must be guarded by lock.

Copy link
Contributor

@hauntsaninjahauntsaninjaMay 7, 2022
edited
Loading

Choose a reason for hiding this comment

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

I'm not sure we need another lock (beyond the GIL) / the previous code seems fine to me. Just need to make sure if enough waiters get removed elsewhere that there are no longernum_to_notify we don't crash.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

The previous version guarded it with a lockand had the try-except. The reason I didn't use try-except was because having both seemed redundant to me. The only way I can think of thatself._waiters could racily lose elements is if a different function removed an element without the lock, which isn't done in any of the methods inCondition.

If preferable, I could add the try-except back.

@AlexWaygoodAlexWaygood added performancePerformance or resource usage stdlibStandard Library Python modules in the Lib/ directory labelsMay 7, 2022
Copy link
Member

@serhiy-storchakaserhiy-storchaka left a comment

Choose a reason for hiding this comment

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

There is a chance to get aKeyboardInterrupt orMemoryError betweenpopleft() andrelease(). You should handle this hard-to-reproduce case.

@dgiger42
Copy link
ContributorAuthor

There is a chance to get aKeyboardInterrupt orMemoryError betweenpopleft() andrelease(). You should handle this hard-to-reproduce case.

@serhiy-storchaka would switching back torelease()ing before taking thewaiter out of the deque fix that, or did the previous version of the code already have a similar issue?

@serhiy-storchaka
Copy link
Member

The previous version of the code already have a similar issue, but with different manifestation.

If you interrupt after releasing the lock, but before removing it from the queue, you will get a RuntimeError next time you callnotify(). If you interrupt after removing the lock from the queue, but before releasing the lock, the waiter thread will hang forever. In the former case you at least notice that something is wrong, in the later case it hangs silently.

We should first fix an issue in the existing code.#92530

@serhiy-storchaka
Copy link
Member

It seems that the proper fix of the interruption bug includes also an optimization similar to this PR.#92534

@dgiger42
Copy link
ContributorAuthor

It seems that the proper fix of the interruption bug includes also an optimization similar to this PR.#92534

Ok. I'll close this PR in favor of#92534

@dgiger42dgiger42 deleted the optimize_condition_notify branchOctober 4, 2022 23:07
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@methanemethanemethane left review comments

@serhiy-storchakaserhiy-storchakaserhiy-storchaka left review comments

@hauntsaninjahauntsaninjahauntsaninja left review comments

Assignees

No one assigned

Labels

awaiting reviewperformancePerformance or resource usagestdlibStandard Library Python modules in the Lib/ directory

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Speed up Condition.notify()

6 participants

@dgiger42@bedevere-bot@serhiy-storchaka@methane@hauntsaninja@AlexWaygood

[8]ページ先頭

©2009-2025 Movatter.jp