Live data from Hacker News

Overhead of Python asyncio tasks

textual.textualize.io

61–70 of 88 posts

Re: Overhead of Python asyncio tasks

#61

Reading this is like reading early Renaissance alchemist arguing about how much mercury they need to combine with how much silver to create gold... This is so far gone I don't even know where to begin... > It may be IO that gives AsyncIO its name, but Textual doesn't do any IO of its own. So why on Earth are you using AsyncIO? You don't need it, if that's true... > Those tasks are used to power message queues How are…

I knew you would be here in the comments. Crabbone won't leave any chance he gets to shit and dump on Python any HN post he can.

Must be so frustrating, knowing that this silly language is one of the most populair programming languages in the world, despite its short comings, one of which is slower performance.

This isn't about python or any language. The extreme negative tone and sense of superiority seems to point to something else.

What is it?

Re: Overhead of Python asyncio tasks

#62

Earlier quoted context omitted.

Matching the cost of a genuine context switch should be a (laughably bad) upper bound for any language's particular concurrency offerings. It is not reasonable.

> It is not reasonable. Reasonableness is relative and use case dependent. The post itself illustrates how the cost is insignificant compared to other "wasteful" operations related to CSS handling. If this is too much overhead for your use case, there are plenty of other approaches and languages to choose from.

If it costs as much as a context switch, you might as well just do context switches. These hosted language scaffoldings - whether that's asyncio, go routines, TPL, Webflux, etc. - exist specifically so you don't have to do a full context switch. If they cost as much as a context switch, they have failed. Regardless of what else is taking time in the system.

If you're not any better, just replace your whole hosted concurrency system with a statement that triggers sched_yield.

Re: Overhead of Python asyncio tasks

#63
post #21

Async Python is still confusing af - when do I need it, what happens under the hood, does it actually help with performance, sometimes the GIL comes into play and sometimes it doesn't, why do we ever use threads at all if there's a GIL, why is it called async io if we can use it for anything. My mind is kind of scattered and people seems to be using a lot of async Python for some reason. Any good resources to clear t…

Async looks like parallelism, but its just smart scheduling. The core concept of async is saying "hey, im waiting for something to complete thats not under my control (like waiting for data on a socket to be able to be read), go ahead and do other things in the mean time".

If you ever coded in sockets in C (and its a good exercise to do so), you probably have at some point ran across `select` which is essentially a non blocking way to check which sockets have data available to read, and then sequentially read the data. This gives the ability for a program to appear parallelized in the sense that it can handle multiple client connections, but its not truly parallel. Different clients can be handled at different time depending on which order they connect, which is asynchronous in nature (versus processing each client in sequence and waiting on each one to connect and disconnect before moving on to the next one)

Async in Python is basically this concept, with a core fundamental feature of time limited execution. Functions can say that they are pausing for x seconds, allowing other functions to run, or functions can say that they give a certain function x seconds to run before resuming execution. If you async code (along with any library you may use) doesn't contain any sleeps or timeouts, its exactly equivalent to synchronous code (since the event loop never really recieves a message that it can suspend a routine or cancel it). With sleeps and timeouts, you gain control over things that can potentially block, both from a caller perspective of not having a function call block your own, and from a callee perspective of not making your function blocking.

The use case is for it is that it is good for I/O bound operations like Threading is, but with the addition that you don't have to worry about synchronization or race conditions, since by design your code will have predictable access patterns. The downside is that your code and any libraries that you use within your code has to be implemented as async libraries, and any library that is async has to have async wrappers around the calls to its methods, which in turn means that your entire code has to be async.

Threading with Python is generally not useful, as its not true parallelism because of GIL. GIL allows only one thread in Python to run. Threading is safer in Python because of this, however it obviously has drawbacks. In general its best used if you want asyncio like performance with a library that is not written with async, since GIL is smart enough to detect when a thread is waiting for input and switch context.

True parallelism in Python is achieved with multiprocessing, however the use case is a little different. Rather than spinning off processes, you generally launch a bunch of worker processes up front (to avoid the larger overhead), then use smart scheduling to distribute work between these processes. Here though you do have to worry about race conditions and synchronization, and use things like locks and mutexes.

Re: Overhead of Python asyncio tasks

#64
post #42

JavaScript is 10-37x faster out of the box without any imports async function time_tasks(count=100) { async function nop_task() { return performance.now(); } const start = performance.now() let tasks = Array(count).map(nop_task) await Promise.all(tasks) const elapsed = performance.now() - start return elapsed / 1e3 } for (let count = 100000; count Outputs (Python 3.11, Bun 0.5.1): % bun textual.ts 100000: 3767797.000…

FWIW, Mac Air, dual core i7 1.7GHz

    $ deno run tasks.js 
    100000: 2777777.777777778 tasks/sec
    200000: 3225806.4516129033 tasks/sec
    ...
    800000: 2395209.580838323 tasks/sec
    900000: 1679104.4776119404 tasks/sec
    1000000: 1851851.8518518517 tasks/sec

Re: Overhead of Python asyncio tasks

#65
I preferred gevent (it's been probably 10 years since I've used it.) Yes, you need a ton of monkey patching, etc... but it was less intrusive once you had everything set up. Sprinkling await and async everywhere always struck me as inelegant.

Re: Overhead of Python asyncio tasks

#66

Reading this is like reading early Renaissance alchemist arguing about how much mercury they need to combine with how much silver to create gold... This is so far gone I don't even know where to begin... > It may be IO that gives AsyncIO its name, but Textual doesn't do any IO of its own. So why on Earth are you using AsyncIO? You don't need it, if that's true... > Those tasks are used to power message queues How are…

This reply strongly reads of 'im smarter than eveyone' and 'know everything.' Is it possible that the author is doing something that you don't know about? Such as writing and reading text to sockets (which would be I/O.) And is it possible they may have a reason to be using asyncio in Python (which uses a single main thread and hence needs something like asyncio for concurrency.) >Needless to say that the whole bench…

> This reply strongly reads of 'im smarter than eveyone'

Dude, where's everyone, where?

I'm smarter than the guy who posted this nonsense about asyncio, that's for sure, but that's a very low bar...

Now, when it comes to Python, then, it's an environment that is flooded with the programmers with the lowest skill level imaginable. This is where all those month-long bootcamps pump their graduates, this is where all the people who took a month-long intro to CS with Python class go, this is where a lot of people who only use Python accidentally, to compliment some other programming activity (or just general computer-related activity) go. It's a swamp, and there's no reason to pretend it isn't.

On the other hand, anyone who had any serious aspirations for Python left the scene ten or so years ago. Today, Python is the worst parts of Java and PHP combined. So, again, it's a very low bar to be better than most Python programmers. Without even trying, when I searched for a job and had to do a bunch of automated assessment tests, I was consistently placed in the "best" decile, often in the "best 5%" of all applicants, and I hate the language. I'm honestly not good at it and don't want to be good at it. You don't need to try hard to be "as good" as I am, because I'm not good... but, yeah, in this particular area everyone is hands down awful.

I also had to interview about two dozens of applicants in my last job. I had people who couldn't explain the difference between expression and statement. I had people who couldn't tell what __str__() method is for. I had extremely low expectations, and yet I was consistently disappointed by the knowledge level of applicants. It's surreal what's going on there.

---

> Overhead startup isn't worthless.

Yeah, maybe... OP never measured it anyways. OP never created any asynchronous I/O tasks. OP measured how long does it take to run couple functions in Python. Admittedly, it takes a long time, but it's irrelevant to async I/O. Especially in the context of comparing whatever OP's doing to threads. Which was their goal stated in the opening statement.

Re: Overhead of Python asyncio tasks

#67
post #9

Mostly a testament to how absurdly fast modern CPUs are despite Python itself being so slow. / Recent Python convert, in spite of the horrible general performance of the official implementation of the language. That sweet, sweet module library. Also, with Docker containers the deployment issues have been solved. It might be slow to execute but it's really efficient to develop with.

This has always been the case. Computing power doubles every few years, and it's cheap (probably less than 10% of your total project cost, unless you are doing highly specific stuff). It doesn't make sense to optimise for CPU cycles as the real bottleneck is usually developer efficiency, I/O, and UX.

Re: Overhead of Python asyncio tasks

#68
Whenever I had to run a lot of Python tasks I preferred Celery over asyncio.

I only ever write an asyncio daemon when I want to launch and manage the results of a bunch of Celery tasks.

Not speaking from some superior position of research here, I'm just saying what I prefer to use.

Re: Overhead of Python asyncio tasks

#69
post #36
post #26

Python is my strongest language. If you ask me to write some asynchronous code I will try my best not to write it in Python. Usually it's just not worth it.

Have you not used async in Python lately? IMO it's very easy to do.

I don't have huge experience with Python, but I used async code with C#/Typescript and lately I had to use some asyncio magic.

I found this article: https://blog.dalibo.com/2022/09/12/monitoring-python-subproc... and while async/await syntax is the same, it's not entirely clear for me, why there's some event loop and what exactly happens, when I pass function to asyncio.run(), like here: https://github.com/pallets/click/issues/85#issuecomment-5034...

So, you can use it and it's not that hard, but there are some parts that are vague for me, no matter which language implements async support.

Re: Overhead of Python asyncio tasks

#70
post #13

Reading this is like reading early Renaissance alchemist arguing about how much mercury they need to combine with how much silver to create gold... This is so far gone I don't even know where to begin... > It may be IO that gives AsyncIO its name, but Textual doesn't do any IO of its own. So why on Earth are you using AsyncIO? You don't need it, if that's true... > Those tasks are used to power message queues How are…

asyncio is really not all about I/O though, despite the name. You can just as easily use it for concurrency by interleaving tasks with each other. You can imagine multiple UI elements that all need to make progress, and using coroutines to have them cooperatively yield to each other and not just have one element block progress everywhere else. It's just using asyncio as a task scheduler, nothing more, nothing less. M…

[flagged]
Post reply on HN