Skip to content

Conversation

stepancheg
Copy link
Contributor

@stepancheg stepancheg commented Sep 3, 2025

Resolved #58 (not sure, completely or not).

Previous PR #62 improves the situation, this improves it further.

This PR includes #59.

@stepancheg
Copy link
Contributor Author

Can I have code review here please?

This PR may or may not lead to performance degradation depending on use case, but I'm fairly certain this PR is correct even if it makes performance worse in certain scenarios.

Normal well-behaving Python thread may legally hold GIL for 5 milliseconds at a time (more if a thread is doing some operations which are supposed to be fast, but in fact slow like some operations on very large lists which are atomic). It is worse if there is large number of threads, and especially if an app is CPU-bound.

Given that, call to Python::attach may block tokio runtime for quite a long time, which is not compatible with how tokio is meant to be used.

Maybe @kylebarron?

where
F: Future<Output = PyResult<T>> + Send + 'static,
T: for<'py> IntoPyObject<'py>,
T: for<'py> IntoPyObject<'py> + Send + 'static,
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is a breaking change, right? Should we highlight that in the Changelog? What if someone wants to use this with a non-Send return type?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Practically it is uncommon to have a future which is Send, but result is not Send.

However, generic code (like generic wrappers of future_into_py) is affected, so it is worth highlighting in changelog. Will do.

if e.is_panic() {
// We should not hold GIL inside async-std/tokio event loop,
// because a blocked task may prevent other tasks from progressing.
R::spawn_blocking(|| {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Kinda hard to tell from the diff, but the only change here is the addition of spawn_blocking?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes.

There is "hide whitespace" option in GitHub diff viewer.

Image Image

@stepancheg
Copy link
Contributor Author

Updated the changelog.

Copy link
Collaborator

@kylebarron kylebarron left a comment

Choose a reason for hiding this comment

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

Ideally I'd love to get another approval before merging.

Also, the release cadence for breaking releases of pyo3-async-runtimes usually matches the upstream pyo3 version, and pyo3 0.26 was just released, so I'm not sure on the release timeline for this.

@stepancheg
Copy link
Contributor Author

As long as this is committed, we can use revision from git (and report back if we find something wrong with it).

@davidhewitt or @iksteen maybe you could also approve the PR?

Copy link
Contributor

@iksteen iksteen left a comment

Choose a reason for hiding this comment

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

Looks solid to me. Also tested this in our production environment and performance seems to be about the same if not slightly better for us.

Copy link
Member

@davidhewitt davidhewitt left a comment

Choose a reason for hiding this comment

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

Also seems reasonable to me, thanks.

Agreed this is breaking so we'd need to hold back for PyO3 0.27 (which I expect in ~1 month when Python 3.14 is final), unless we wanted to break the versioning alignment.

@kylebarron
Copy link
Collaborator

Thank you two for the reviews!

@kylebarron kylebarron merged commit 94b1c25 into PyO3:main Sep 18, 2025
35 checks passed
@stepancheg stepancheg deleted the with-gil-2 branch September 18, 2025 14:06
@stepancheg
Copy link
Contributor Author

FWIW, in the last days after we starting using this change, our GIL situation seems improved, although we cannot say that with 100% confidence because there are too many changes in Python code happened, and monitoring for our python clients is not perfect.

We did not observe regressions though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Do not call Python::attach inside tokio task as it can freeze non-Python-related tasks
4 participants