Live data from Hacker News

A conceptual overview of asyncio

github.com

11–20 of 32 posts

Re: A conceptual overview of asyncio

#11
post #5

Great read! Python asyncio can really screw up your runtime performance if you use it poorly. And it's _really_ easy to use poorly. Consider a FastAPI server using asyncio instead of threading. _Any_ time you drop down into a synchrononous API, you better be sure that you're not doing anything slow. For example, encoding or decoding JSON in Python actually grabs the GIL depending on what library you're using, and the…

That's a GIL problem not an async problem. Even if you choose to ditch asyncio and use threads, you still need to care about the GIL. And when I use asyncio I don't worry about CPU-bound tasks like encoding or decoding JSON; I worry about some library doing I/O synchronously regardless of whether such library releases the GIL or not.

Re: A conceptual overview of asyncio

#12
post #9

> Frankly, I'm not sure why that design decision was made and find it rather confuses the meaning of await: asynchronously wait. I've always understood it to mean "wait for asynchronous object", not that the wait itself is asynchronous. It's just an English word that roughly means "wait for", that was chosen for the nice "a" prefix for asynchronous stuff.

Mmm fair point! Though, coroutines aren't really asynchronous objects in that usage, right? Since `await coroutine` would run that coroutine synchronously.

Re: A conceptual overview of asyncio

#13
post #11
post #5

Great read! Python asyncio can really screw up your runtime performance if you use it poorly. And it's _really_ easy to use poorly. Consider a FastAPI server using asyncio instead of threading. _Any_ time you drop down into a synchrononous API, you better be sure that you're not doing anything slow. For example, encoding or decoding JSON in Python actually grabs the GIL depending on what library you're using, and the…

That's a GIL problem not an async problem. Even if you choose to ditch asyncio and use threads, you still need to care about the GIL. And when I use asyncio I don't worry about CPU-bound tasks like encoding or decoding JSON; I worry about some library doing I/O synchronously regardless of whether such library releases the GIL or not.

This is spot on. GIL-less python will be a thing, and when it happens, there will still be no reason to combine asyncIO with thread primitives. Waiting for IO can be spun off into a new thread, and it will work as you expect it would.

Trying to combine mental models of asyncio and threading is a model for pure insanity.

Re: A conceptual overview of asyncio

#14
This is great, thank you! Python's asyncio has certainly confused me more than other languages' async-await implementations.

Nit in [1]: When timing durations inside of a program it's best to avoid the system clock as it can and does jump around. For Python, prefer time.monotonic() or time.perf_counter() over time.time() in those situations.

[1] https://github.com/anordin95/a-conceptual-overview-of-asynci...

Re: A conceptual overview of asyncio

#15
I like how asyncio could just be built off of generators, and how it all ... well it mostly works, and it works well enough for people who care enough to make a whole async stack.

I am very unhappy with asyncio leading to the gold rush of a lot of people writing "async-capable" libraries that all make (IMO) really gnarly design decisions in the process. I have seen loads of newer Python projects that take async-capable libraries that make life harder for people who like shipping stable software.

Meanwhile a lot of existing libraries/frameworks that just have more "serious" overall designs have to churn quite a bit to support sync and async workflows.

I care a lot about Django getting async ORM support in theory, but at this point I don't know how that's happening. My current mentality is crossing my fingers that something akin to virtual threads[0] happens

[0]: https://discuss.python.org/t/add-virtual-threads-to-python/9...

Re: A conceptual overview of asyncio

#16
post #15

I like how asyncio could just be built off of generators, and how it all ... well it mostly works, and it works well enough for people who care enough to make a whole async stack. I am very unhappy with asyncio leading to the gold rush of a lot of people writing "async-capable" libraries that all make (IMO) really gnarly design decisions in the process. I have seen loads of newer Python projects that take async-capab…

You could use gevent. It uses green threads, so that the code you write looks like synchronous code. It can also monkeypatch core networking modules so that existing code will work without changes (including the Django ORM).

Re: A conceptual overview of asyncio

#17
post #9

> Frankly, I'm not sure why that design decision was made and find it rather confuses the meaning of await: asynchronously wait. I've always understood it to mean "wait for asynchronous object", not that the wait itself is asynchronous. It's just an English word that roughly means "wait for", that was chosen for the nice "a" prefix for asynchronous stuff.

Mmm fair point! Though, coroutines aren't really asynchronous objects in that usage, right? Since `await coroutine` would run that coroutine synchronously.

i don't think that's the case. an await coroutine requires you to be asynchronous because you are implicitly suspending yourself until the awaited function completes (and through however many suspensions the awaited function creates). an await can never be synchronous, you need to pull in an event loop to close between asynchronous functions and sync-land, not an await.

Re: A conceptual overview of asyncio

#18
post #9

> Frankly, I'm not sure why that design decision was made and find it rather confuses the meaning of await: asynchronously wait. I've always understood it to mean "wait for asynchronous object", not that the wait itself is asynchronous. It's just an English word that roughly means "wait for", that was chosen for the nice "a" prefix for asynchronous stuff.

Mmm fair point! Though, coroutines aren't really asynchronous objects in that usage, right? Since `await coroutine` would run that coroutine synchronously.

[deleted]

Re: A conceptual overview of asyncio

#19
post #5

Great read! Python asyncio can really screw up your runtime performance if you use it poorly. And it's _really_ easy to use poorly. Consider a FastAPI server using asyncio instead of threading. _Any_ time you drop down into a synchrononous API, you better be sure that you're not doing anything slow. For example, encoding or decoding JSON in Python actually grabs the GIL depending on what library you're using, and the…

JSON encoding is, as someone else points out, a GIL problem, but I want to add that even if you do JSON encoding in an async context:

  async def foo(…):
    json.dumps(d)  # you're blocking the event loop
You're still going to block on it.

  def sync_foo(…):
    json.dumps(d)  # you're holding the GIL … and so blocking here too
Short of resolving the GIL somehow (either by getting ridding of it, which I think is still a WIP though it has been "merged", I believe) or subinterpreters, etc., JSON is inherently going to need to hold the GIL while it walks the structure it is encoding. (Unlike a large file I/O, where it might be possible to release the GIL during the I/O if we have a strong ref to an immutable buffer.)
Post reply on HN