Python Asyncio
121–130 of 188 posts
Re: Python Asyncio
#122After 2 years of using asyncio in production, I recommend to avoid it if you can. With async programming, you take the complexity of concurrent programming, which is way harder than you can imagine. Also nobody mentions this for some reason, but asyncio doesn't make your programs faster, in fact it makes everything 100x SLOWER (we measured it multiple times, compared the same thing to the sync version), but makes you…
I've used curio as an alternative concurrent programming engine for a med-large project (and many small ones). In comparison to asyncio, it's a joy to use.
Re: Python Asyncio
#123After 2 years of using asyncio in production, I recommend to avoid it if you can. With async programming, you take the complexity of concurrent programming, which is way harder than you can imagine. Also nobody mentions this for some reason, but asyncio doesn't make your programs faster, in fact it makes everything 100x SLOWER (we measured it multiple times, compared the same thing to the sync version), but makes you…
You wouldn't do it that way for any reason other than you can get better performance than way than by using threading or other pre-emptive multitasking.
It's not a better developer experience than writing straight forward code where threads are linear and interruptions happen transparently to the flow of the code. There are foot guns everywhere, with long running tasks that don't yield or places where there are hidden blocking actions.
It reminds me a bit of the old system 6 mac cooperative multitasking. It was fine, and significantly faster because your program would only yield when you let it do it, so critical sections coule be guaranteed to not context shift. However, you could bring the entire machine to a halt by holding down the mouse button, as eventually an event handler would get stuck waiting for mouse up.
Pre-emptive multitasking was a huge step forward -- it made things a bit slower on average, but the tail latency was greatly improved, because all the processes were guaranteed at least some slice of the machine.
Re: Python Asyncio
#124Earlier quoted context omitted.
This is an insane take, if you are doing async you already HAVE a need for concurrent programming. Async just makes that simpler to read and write.
I'm pretty sure a lot of people don't understand the tradeoffs and don't really need concurrent code. There are really only a couple of use-cases where it's really handy: for example an API gateway, where you only get and send HTTP requests. Other than that, I don't see how it worth the insane complexity (compared to sync code). You can write web servers in a sync manner; Flask, Django is way better if you only need…
Re: Python Asyncio
#125After 2 years of using asyncio in production, I recommend to avoid it if you can. With async programming, you take the complexity of concurrent programming, which is way harder than you can imagine. Also nobody mentions this for some reason, but asyncio doesn't make your programs faster, in fact it makes everything 100x SLOWER (we measured it multiple times, compared the same thing to the sync version), but makes you…
I'd need to know the methodology. Asyncio is "gated", meaning that coroutines execute in tranches. When you queue up a bunch of coroutines from another coroutine, they don't execute right away instead they go in a list. Then when the current tranche completes the next one starts. There's some tidying up which occurs with every tranche.
As an (only one) example of "measuring the wrong thing", if you queue up a single task 1000 times which takes as its argument a unique timer instance it matters whether you queue them up one at a time as they finish running or queue them all up at once.
#!/usr/bin/python3
# (c) 2022 Fred Morris, Tacoma WA USA. Apache 2.0 license.
"""Illustrating the tranche effect in asyncio."""
from time import time
import asyncio
N = 1000
class TimerInstance(object):
def __init__(self, accumulator):
self.accumulator = accumulator
self.start = time()
def stop(self):
self.accumulator.cumulative += time() - self.start
return
class Timer(object):
def __init__(self):
self.cumulative = 0.0
return
def timer(self):
return TimerInstance(self)
async def a_task(timer):
timer.stop()
return
def main():
loop = asyncio.get_event_loop()
timing = Timer()
overall = time()
for i in range(N):
loop.run_until_complete( loop.create_task( a_task(timing.timer()) ) )
print('Sequential: {} Overall: {}'.format(timing.cumulative, time() - overall))
timing = Timer()
overall = time()
for i in range(N):
loop.create_task( a_task(timing.timer()) )
loop.stop()
loop.run_forever()
print('Tranche: {} Overall: {}'.format(timing.cumulative, time() - overall))
if __name__ == '__main__':
main()
# ./tranche-demo.py
Sequential: 0.02229022979736328 Overall: 0.04146838188171387
Tranche: 6.084041595458984 Overall: 0.012317180633544922Re: Python Asyncio
#126Earlier quoted context omitted.
Ok. This is what has been a huge hangup for me. It really seems that if you're doing asyncio, you must do EVERYTHING async, it's like asyncio takes over (infects?) the entire program.
That's exactly the opposite of what it says really: if you need to do CPU stuff, then you can do that, it just won't be using asyncio. So it doesn't really infect your whole program. You could easily have, say, a thread to do all your asyncio stuff, another to do some CPU intenstive stuff (so long as it blocks the GIL) and yet another to do some blocking I/O e.g. interacting with a database with its own blocking APIs…
Modern frameworks should be orthogonal and compositional. Even orthogonality (when you use multiple frameworks, each framework solves a problem along a different "axis" and does not interact with any of the other axes) is optional.
Compositionality means I should be able to combine several systems without one affecting the other unnecessarily. async does not fulfill that requirement.
Re: Python Asyncio
#127Earlier quoted context omitted.
any concurrency system that is properly designed supports both types of tasks.
I only know C#: https://learn.microsoft.com/en-us/dotnet/csharp/async#recogn... There you also have to act differently based the task
The docs on that page also point you to a different task library which does what I'd expect:
"If the work is appropriate for concurrency and parallelism, also consider using the Task Parallel Library."
I checked those docs and that is a framework that makes sense.
Re: Python Asyncio
#128After 2 years of using asyncio in production, I recommend to avoid it if you can. With async programming, you take the complexity of concurrent programming, which is way harder than you can imagine. Also nobody mentions this for some reason, but asyncio doesn't make your programs faster, in fact it makes everything 100x SLOWER (we measured it multiple times, compared the same thing to the sync version), but makes you…
My opinion is that async/evented is a (useful) performance hack. You wouldn't do it that way for any reason other than you can get better performance than way than by using threading or other pre-emptive multitasking. It's not a better developer experience than writing straight forward code where threads are linear and interruptions happen transparently to the flow of the code. There are foot guns everywhere, with lo…
"Scalability" is a better word to use when talking about asyncio. Along with describing complex concurrent programming such as for a GUI, where the added syntactical complexity if outweighed by the reduced boilerplate of traditional GUI programming.
Re: Python Asyncio
#129Earlier quoted context omitted.
> reworking your DB access patterns may gain you more. Nope: https://techspot.zzzeek.org/2015/02/15/asynchronous-python-a...
I don't say that asyncio gives you nothing! Go for it with your DB access if you have already gone async in your design. But often the lower-hanging fruit is doing more joins in the DB, fetching fewer columns, and writing your query more thoughtfully. Async only helps if you can do something while waiting for the DB to complete your query. A common anti-pattern, exacerbated by ORMs, is doing a bunch of small queries…
Reluctant to add a "me-too" comment but I think you have it there. For whatever reason people are much keener to investigate different ways of scheduling IO than they are to investigate what the query plan looks like and why.
Re: Python Asyncio
#130Earlier quoted context omitted.
Async python by design is not concurrent, nothing is executing at the same time on different cores/threads. There's one worker loop and one task running on it at a time.
Concurrency is not Parallelism. You should watch this quintessential talk about the difference - https://www.youtube.com/watch?v=oV9rvDllKEg