12 ms·
Python Asyncio
- brrrrrm 4y agoImportant to note: > They are suited to non-blocking I/O with subprocesses and sockets, however, blocking I/O and CPU-bound tasks can be used in a simulated non-blocking manner using threads and processes under the covers. If you're using it for anything besides slow async I/O, you're going to have to do some heavy lifting. I've also found the actual asyncio implementation in CPython to be slow. Measuring purely event-loop overhead (and doing little/nothing in the async spawned tasks), it's 120x slower than JavaScript on my machine. https://twitter.com/bwasti/status/1572339846122991617 https://twitter.com/bwasti/status/1572339846122991617
- bjt2n3904 4y agoOk. 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.
- nrmitchi 4y agoYes. Unless you (and your team) are well-versed with python and how async works, and all the dependencies you use, is it very easy to accidentally do something blocking in async and lose most of the benefits.
- nicolaslem 4y agoTo be fair this is not really asyncio's fault, the same happens in most languages unless the runtime does some magic like scheduling blocking calls in a background thread (which can also be done with asyncio).
- brrrrrm 4y agoI feel the same way, it's a lot like `const` in C++. Basically it's enforcing usage for every upstream user to ensure there's no inefficiency (such as waiting for things like the network). JavaScript has an extremely nice "out" (I'm sure other languages do too): async function() { await async_thing() do_sync_stuff() } can be written function() { async_thing().then(do_sync_stuff) } which is quite intuitive and helps glue code together. I think the callback-based thinking really clarifies user intent ("just tell me when it's done") without impacting performance.
- gpderetta 4y agoproblem is async doesn't enforce anything. You can still block from an async function.
- quietbritishjim 4y agoThat'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. In that case, you could spawn separate threads and exchange messages between them like usual. Where this falls down a little is if you want asyncio to infer your whole program - or more accurately, if you want to use it in all of the task-management code at the top level of your app. In that case, you would use asyncio's thread API [1] although it's a bit clunky for when you want to maintain state bound to a specific worker thread (like SQLite database objects). [1] https://docs.python.org/3/library/asyncio-task.html#running-in-threads https://docs.python.org/3/library/asyncio-task.html#running-...
- brrrrrm 4y agoI think the issue is more like this: 1. You jump into a huge codebase and find a very useful function you want to use in your code (it uses asyncio) 2. Your code doesn't use asyncio, so you start converting functions to be async (or else you can't use the `await` keyword) 3. It turns out your function is called by a bunch of different users, some of which do not use the asyncio runner 4. You end up having several meetings with upstream teams asking them to use the asyncio runner 5. A single team says "no" 6. Scrap the project and just rewrite that original function you found synchronously
- quietbritishjim 4y agoI guess I was focusing more on the CPU task problem mentioned at the top. But you're talking about blocking IO - more specifically, blocking IO that you want to convert to async (not just run in a worker thread using the thread-to-async API I mentioned). What you've written is true, but "infects" a smaller proportion of the code than you'd expect, in my experience. In fact, the better organised the program is, the less needs to change when converting to async. For example, reading from a connection your top-level async function would often be something like this: async def read_and_handle_messages(connection): while True: next_message_bytes = await connection.get_next_message() next_message_parsed = my_parser.parse(next_message_bytes) my_message_handler(next_message_parsed) All the application-specific code is in the parser and the message handler but neither of those are async. (If you need to send a response, your message handler could post a message to an async queue that is read by a separate writer task.) In your hypothetical scenario, you'd maybe write two a wrapper functions, one for blocking and one for async, which both read the message, parse it and handle it. But that only needs to be two versions of a three line function while all the subtantial code is completely shared. I find that there's very little actual async code in async programs that I write, even with no blocking IO historical baggage. Admittedly, that's partly because I organise programs to reach that goal, but it actually works out for the best because all the async-task lifecycle management ends up in one place, which makes following overall program flow particularly easy.
- acedTrex 4y agoYes async is viral, its all or nothing
- maxbond 4y agoAs someone who has written an application with sync and async Python components within the same process, it is all, nothing, or pain. (If you really, really need to do this - triple check - use queues & worker threads to decouple the sync parts and keep them out of your event loop thread, as a sort of sync-async impedence match.)
- evilduck 4y agoThe propagation/infection of async handling is just indicitive of the nature of the problem. Try writing async code in any other language and you see similar patterns emerge.
- jnwatson 4y agoThat's 80% due to the "what color is your function" problem. There are bridges from async to sync and vice versa, but they must be used very sparingly, as they aren't nestable.
- est 4y agoMissing yet very important topics: redis & db drivers in async. Or even async ORM.
- m3047 4y agoI do Redis in a thread pool. Did this before aioredis came out, have kept doing it because I know it and it works. Have used the same pattern for a few other things it works so well.
- deleted 4y ago[deleted]
- chaostheory 4y agoIs this negligible in performance until the GIL radically changes? I find parallel processing has muc larger increases in speed.
- yoyohello13 4y agoSince async is single threaded the GIL shouldn't come into play.
- evilturnip 4y agoQuestion though: asyncio is implemented as threads, which is where the GIL chokes, right?
- L3viathan 4y agoasyncio is _not_ implemented as threads. It has features where it can wrap a sync function inside a thread in order to turn it into an async function, but if you just write "normal" async code, all your code is running in a single thread.
- evilturnip 4y agoAh, ok that makes more sense.
- deleted 4y ago[deleted]
- ddorian43 4y agoToo bad Python couldn't go the gevent road. At least Java is doing with Project Loom and looks like it will be very successful.
- greyman 4y agoMaybe off-topic, but my advice would be: if you need this guide, consider to switch to another language, if that's possible. In our company we switched to Go, and all those asyncio problems were magically solved.
- austinpena 4y agoAgreed. Moving my Python data analytics to a GRPC server that I call from a Go service has been _so much_ easier to manage and debug.
- pantsforbirds 4y agoI've had absolutely no problems using async programming in python. It's extremely easy to setup a script in 100-200 lines of code to do something like: pull the rows from postgres that match query <x>. Process the data and push each row as an event into rabbitmq. In <200 lines of code i was easily processing 25k/rows per second and it only took me a few minutes to figure out the script.
- akdor1154 4y agoI love Python and fully agree with you. :(
- quietbritishjim 4y agoNot complete - doesn't include Task Groups [1] In fairness they were only included in asyncio as of Python 3.11, which was released a couple of weeks ago. These were an idea originally from Trio [2] where they're called "nurseries" instead of "task groups". My view is that you're better off using Trio, or at least anyio [3] which gives a Trio-like interface to asyncio. One particularly nice thing about Trio (and anyio) is that there's no way to spawn background tasks except to use task groups i.e. there's no analogue of asyncio's create_task() function. That is good because it guarantees that no task is ever left accidentally running in the background and no exception left silently uncaught. [1] https://docs.python.org/3/library/asyncio-task.html#task-groups https://docs.python.org/3/library/asyncio-task.html#task-gro... [2] https://github.com/python-trio/trio https://github.com/python-trio/trio [3] https://anyio.readthedocs.io/en/latest/ https://anyio.readthedocs.io/en/latest/
- dang 4y agoOk, we've taken completeness out of the title above.
- Steltek 4y agoPython, more than other languages, ends up being used in utility scripts on end user devices, where you'll find just about everything. Python's async seems to still have a large swing in available features. Unlike async methods in other languages, semi-serious dabbling in it just for fun is courting a lot of headaches later.
- throwaway81523 4y agoI have such a feeling of tragedy about Python. I wish it had migrated to BEAM or implemented something similar, instead of growing all this async stuff. Whenever I see anything about Python asyncio, I'm reminded of gar1t's hilarious but NSFW rant about node.js, https://www.youtube.com/watch?v=bzkRVzciAZg https://www.youtube.com/watch?v=bzkRVzciAZg . Content warning: lots of swearing, mostly near the end.
- rogers12 4y agoThat's a blast from the past. Incredible that 10 years ago people thought using a thread per request is a good idea because anything else is too hard.
- kissgyorgy 4y agoAfter 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 your program concurrent (NOT parallel), where the tradeoff is you use more CPU, maybe less memory, and can saturate your bandwidth better. Never do anything CPU-bound in an async loop!
- acedTrex 4y agoThis 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.
- throwawaymaths 4y ago> Async just makes that simpler to read and write. Really? I definitely had a huge struggle reading async python, because generators and yields break the concept of "what is a function" and struggled writing async python because of function coloring.
- andrewstuart 4y agoDay to day Python async should be using generators and yields.
- nine_k 4y agoGenerators are great for predictable concurrency. Things like asynchronous I/O, with timeouts and stuff, require more support on the language and stdlib level.
- dekhn 4y agoI am really not a fan of generators and yields for the same reason. But over time I've come to see it as ever-so-slightly more elegant syntax sugar for a class that maintains internal state to sequentially return specific values in response to a series of calls to a function.
- bityard 4y agoI bet the actual content here is great, but I find the page to be unreadable with the large text, huge amounts of whitespace, and quotes (with Amazon referral links) sprinkled in between every other sentence.
- samwillis 4y agoThere is very little in everyday Python usage that benefits from Asyncio. Two in webdev, are long running request (Websockets, SSE, long polling), and processing multiple backend IO processes in parallel. However the later is very rare, you may think you have multiple DB request that could use asyncio, but most of the time they are dependent on each other. Almost all of the time a normal multithreaded Python server is perfectly sufficient and much easer to code. My recommendation is only use it where it is really REALY required.
- nicolaslem 4y agoAgreed, the SaaS Python application I maintain does SSE with threads. It is not the prettiest thing but it works and threads are cheaper than rewriting the whole thing to be async.
- dividuum 4y agoI never understood why gevent wasn't integrated more into default Python. I think at the moment it still requires monkey patching, so non-aware functions use the gevent variants. But once you've done that, you can gevent.spawn() a normal python function and it also runs concurrent (though not parallel) and is suspended when blocking I/O happens. No function coloring required. I'm sure there is some reason why that wasn't done. Anyone knows?
- kissgyorgy 4y agoFully agree with this! Just stick to Flask/Django if you doing a simple website/API. Async also makes DB connections slower, here is a great piece from Mike Bayer from years ago: https://techspot.zzzeek.org/2015/02/15/asynchronous-python-and-databases/ https://techspot.zzzeek.org/2015/02/15/asynchronous-python-a...
- usrbinbash 4y agoCompletely agree with this. I have several python services running as glue between some of our components. They all use threading. I find it alot easier to reason about.
- 4y ago
- grodes 4y agoasync is not comparable to threads: - async is concurrency - threads are parallelism They are not exclusives, the best approach is to be multi-threaded while each of the threads uses concurrency to prevent blocking the cpu.
- gpderetta 4y agoThreads are also for concurrency. In fact in python because of the GIL they are pretty much only for concurrency.
- ollien 4y ago> - async is concurrency - threads are parallelism Even this isn't necessarily true, especially given you can limit a process to a single core (or, if you use a single core system, lest we forget those exist!), or, in Python's case, the GIL! You can still have parallelism with asynchronous programming, it's just not necessarily guaranteed. IIRC tokio lets you spin up runtimes on different threads which (putting the above caveat) _can_ run in parallel.
- djha-skin 4y agoJust in time, I've been needing to implement s3 upload asynchronously.
- PyWoody 4y agoAre you sure it's worth the complexity? Threads will drop the GIL for the duration of the network bound I/O .
- djha-skin 4y agoGood point!
- xtreak29 4y agoDoes aioboto3 help here? https://aioboto3.readthedocs.io/en/latest/usage.html#upload https://aioboto3.readthedocs.io/en/latest/usage.html#upload
- RantyDave 4y agoI did it through 'multiprocessing' and a Pipe. Works fine but challenging shutting everything down when the child process throws an exception.
- ltbarcly3 4y agoPython asyncio is pretty awful. The libraries are of extremely poor quality, and the slightest mistake can lead to blocking the event loop. After a few years of dealing with it I refuse to continue and am just using threads.
- nineplay 4y agoNot mentioned: The behavior is different between python 3.6 and 3.8. That was fun to debug. Python is simply not the right language for asynchronous programming. Things that are easy in many other languages are hard and don't work as you'd expect. If you are in a python-only shop, brush up on your presentation skills and see if you can convince them to branch out. Or write a shell script. You're better off with "./read_socket.sh &" than you are with any python library.
- brrrrrm 4y agoAll of distributed machine learning would benefit from async, but it's unfortunately a Python-only ecosystem for the time being. Probably gonna be a couple years before that has a chance of changing
- nine_k 4y agoHow would ML benefit from async? I thought everything interesting in things like TF or PyTorch is done by native code which is free to use multithreading and anything at all. (I know little about ML.)
- brrrrrm 4y agoSpecifically distributed would be helped (multiple nodes). Right now the typical paradigm is this really clunky lock-step across nodes waiting for each other (everything is blocking). If your hardware is non-homogenous (both interconnects and accelerators) or your program needs to be run in a pipelined way, you're fighting an extremely uphill battle. Go, JavaScript etc are the usual languages of choice for this type of stuff because it's easy to express non-blocking code.
- nine_k 4y agoI suspect multiprocessing + shared memory could help this. The stdlib has provisions for both, but a coordination layer is needed. That would be closest to true multithreading.
- whalesalad 4y agoGevent is the only way I will do async in Python. Everything else ends up being a nightmare, and gevent is a lot more performant than I ever imagine it will be for a given situation.
- ok_dad 4y agoThe only thing I ever use async in Python for is batch requests, like hundreds or thousands of little requests. I collect them up in a task list with context, run them with one of the “run all of these and return the results or errors” functions in the library, then process the results serially. Anything I need to do that doesn’t use this simple IO pattern, like cpu bound workers, I prefer to use processes or multiple copies of the app synchronized with a task queue.
- leveraction 4y agoI have used asyncio through aiohttp, and I have been pretty happy with it, but I also started with it from the beginning, so that probably made things a little easier. My setup is a bunch of microservices that each run an aiohttp web server based api for calls from the browser where communications between services are done async using rabbitmq and a hand rolled pub/sub setup. Almost all calls are non-blocking, except for calls to Neo4j (sadly, they block, but Neo4j is fast, so its not really a problem.) With an async api I like the fact that I can make very fast https replies to the browser while queing the resulting long running job and then responding back to the Vue based SPA client over a web socket connection. This gives the interface a really snappy feel. But Complex? Oh yes. But the upside is that it is also a very flexible architecture, and I like the code isolation that you get with microservices. Nevertheless, more than once I have thought about whether I would choose it all again knowing what I know now. Maybe a monolithic flask app would have been a lot easier if less sexy. But where's the fun in that?
- senko 4y ago> With an async api I like the fact that I can make very fast https replies to the browser while queing the resulting long running job and then responding back to the Vue based SPA client over a web socket connection. This gives the interface a really snappy feel. How does this compare to doing the same with eg. Django Channels (or other ASGI-aware frameworks)? I have yet to find a use case compelling enough to dive into async in Python (doesn't help that I also work in JS and Go so I just turn to them for in cases where I could maybe use asyncio). This is not to say it's useless, just that I'm still searching for a problem this is the best solution for.
- leveraction 4y agoI have never used Django, so I cannot say but if Channels handles the websocket connection back to the client, then I assume you could send back a quick 200 notification as the http response to the user and then send the real results later over the socket. I think these would be equivalent. I have also never used Go, but I am comfortable saying that Python async is much easier to user than JS async. I find JS to be as frustrating as it is unavoidable. Using aiohttp as on api is not bad at all. Once you have the event loop up and running, its a lot like writing sync code. Someone else made a comment about the fact that Python has too many ways to do async because everything keeps evolving so fast. I this this is true. The first time I ever looked at async on Python it was so nasty I basically gave up and reconsided Flask but came back around later because I so despised the idea of blocking by server that I was compelled to give it another go. The next time around was a lot easier because the libraries were so much improved. I think a lot of people think that async Python is harder than it is (now).
- andrewstuart 4y agoI love Python async - it’s a complete game changer for certain types of applications. I find Python async to be fun and exciting and interesting and powerful. BUT it is a big power tool and there’s so much in it that it’s hard to work out how to drive it right. I have pretty good experience with Python and javascript. I prefer Python to javascript when writing async code. Specific example I spent hours trying to drive some processes via stdin/stout/stderr with javascript and it kept failing for reasons I couldn’t determine. Switched to Python async and it just worked. The most frustrating thing about async Python is that it has been improving greatly. That means that it’s not obvious what “the right way” is, ie using the latest techniques. This is actually a really big problem for async Python. I’m fairly competent with it, but still have to spend ages working out if I’m doing it “the right way/the latest way”. The Python project really owes it to its users to have a short cookbook that shows the easiest, most modern recommended way to do common tasks. Somehow this cookbook must give the reader instant 100% confidence that they are reading the very latest official recommendations and thinking on simple asyncio techniques. Without such a “latest and greatest techniques of async Python cookbook” it’s too easy to get lost in years of refinement and improvement and lower and higher level techniques. The Python project should address this, it’s a major ease of use problem. Ironically, pythons years of async refinement mean there’s many many many ways to get the same things done, conflicting with pythons “one right way to do it” philosophy. It can be solved with documentation that drives people to the simplest most modern approaches.
- arecurrence 4y agoThe way that this is formatted... I initially thought it was a Haiku :)
- jmatthews 4y agoJust to swim upstream. For http requests and bounded IO I've found asyncio to be straightforward and a game changer. In the context of call an endpoint with a data payload and have the endpoint process it with outbound http calls it is a 10x'er for very little complexity and no external libraries.
- mpeg 4y agoIn case the author reads this, there is an error in the "How to Execute a Blocking I/O or CPU-bound Function in Asyncio?" [0] It reads: > The asyncio.to_thread() function creates a ThreadPoolExecutor behind the scenes to execute blocking calls. > As such, the asyncio.to_thread() function is only appropriate for IO-bound tasks. It should say it's only appropriate for CPU-bound tasks. [0]: https://superfastpython.com/python-asyncio/#How_to_Execute_a_Blocking_IO_or_CPU-bound_Function_in_Asyncio https://superfastpython.com/python-asyncio/#How_to_Execute_a...
- wrigby 4y agoI think the article is correct here, actually - if you need to run a CPU-bound task, you’ll need a ProcessPoolExecutor.
- danuker 4y agoI second this. Python has a Global Interpreter Lock, so only one Python instruction executes at a time. Async and threads only help you with I/O (where the OS affords waiting for multiple operations in parallel). To execute CPU-bound code in parallel you need multiple processes. I think this is a major disadvantage of Python, because processes are much costlier to spawn, and if you implement long-running workers to avoid frequent spawning, you have to incur serialization/deserialization costs, because shared memory support is very rudimentary (in essence, just fixed size numeric code).
- mpeg 4y agoIt's just awkwardly worded, I think. It probably should include a mention of ProcessPoolExecutor in the following bit where it explains the run_in_executor function to make more sense. Especially as the whole section talks about passing CPU-bound task to a thread pool, but then recommends not to use a thread pool. Though I think the GIL isn't really that big a deal for most CPU-bound code, with plenty of third party libraries and even within the python standard library a lot of the code is not native python, and therefore releases the GIL lock.
- 4y ago
- m3047 4y agoI seem to use asyncio a lot, so maybe it's just good for internet plumbing. Things I've used it for: * A Postfix TCP table. * A milter. * DNS request forwarding. * Reading data from a Unix domain socket and firing off dynamic DNS updates. * A DNS proxy for Redis. * A netflow agent. * A stream feeder for Redis. https://github.com/search?q=user%3Am3047+asyncio&type=Repositories https://github.com/search?q=user%3Am3047+asyncio&type=Reposi... By the way you can't use it for disk I/O, but you can try to use it for e.g. STDOUT: https://github.com/m3047/shodohflo/blob/5a04f1df265d84e69f10af674709af06202546e3/examples/dnstap2json.py#L263 https://github.com/m3047/shodohflo/blob/5a04f1df265d84e69f10... class UniversalWriter(object): """Plastering over the differences between file descriptors and network sockets."""
- gilad 4y agowhat about aiofiles[0] for disk I/O? [0] https://github.com/Tinche/aiofiles https://github.com/Tinche/aiofiles
- m3047 4y agoNot sure. A cursory look suggests it runs file ops in a thread pool. The problem that I'm aware of is at a deeper level and has to do with the ability (or lack thereof) to set nonblocking on file descriptors associated with disk files.
- nerdponx 4y agoYour look is correct, it basically wraps file i/o in to_thread().
- vodou 4y agoI've never bothered to learn Python asyncio. When Python 3.5 came out I just thought it looked overly complex. Coming from a C/C++ background on Linux I just use the select package for waiting on blocking I/O, mainly sockets. Do you think there is something to gain for me by learning asyncio?
- eestrada 4y agoPersonally, I don't think there is a benefit. If select is working for you, asyncio doesn't add anything performance wise. It is just meant to look more synchronous in how you write the code. But, using select and either throwing work onto a background thread or doing work quickly (if it isn't CPU bound) can be just as clear to read, if not clearer. Sometimes "async" and "await" calls only obfuscate the logic more.
- xwowsersx 4y agoI'm not in a much of a position to evaluate Python's asyncio since I really have not used it very much. However, over the last few days, I started to dig into it and tried to get some (what I think are) very basic examples working and really struggled. That alone is not fully dispositive because I've used many async implementations in various languages and each of them have a bit of a learning curve and their own wrinkles you have to ramp up on. That said, my limited experience at least tells me that Python's async has a FUX that leaves a lot to be desired. I've found other languages make it a lot easier to do concurrency, parallelism, async vs sync, blocking vs non-blocking and all that. I don't really know if the issue is poor documentation, the semantics of the APIs themselves...really not sure. I do know that I'm left with the feeling that "this seems like it's going to be a pretty big PITA".
- andrewstuart 4y agoIt IS easy. The Python project just don’t make it obvious how to do it easy.
- xwowsersx 4y agoRight. So you think it's mainly an education/documentation issue? I'm totally open to that in fact being the case. One really simple use case I had was just annotating a method to run async and then calling that in a loop elsewhere which did speed up a bunch of work I was doing pretty dramatically. import asyncio def background(f): def wrapped(*args, **kwargs): return asyncio.get_event_loop().run_in_executor(None, f, *args, **kwargs) return wrapped @background def my_io_bound_function():...
- m3047 4y agoYou need to run the executor somewhere ( loop.run_forever() or loop.run_until_complete() ), that can be in the current thread or a separate thread, keep in mind Python is still conceptually a single core. Things I've found particularly useful: * Optional / debug logging of coroutine start/exit. * Stats logging, including count, runtime, request queue (multiple instances of the same function) depth. * Printing tracebacks within the coroutine context. Haven't expended any effort on decorators, good for you.
- PointyFluff 4y agoWhy do yo inject quotes randomly everywhere throughout the document? Why is only 1/3 of the screen used for content?
- hoten 4y agoThis is really wordy. Anyone have an alternative introduction to asyncio?
- dekhn 4y agoI've used python since 1995 and I can say that async is one of the worst things I've seen put into python since then. I've used a wide range of frameworks (twisted, gevent, etc) as well as threads and even if async is a good solution (I don't think it is) it broke awscli for quite some time (through aiobotocore and related package dependencies). It's too late in the game for long-term breaks like that or any backward-incompatible changes impacting users.
- btown 4y agoYep, it's 2022 and gevent is still the only solution for async & high concurrency that Just Works with the entire ecosystem of Python libraries without code changes. There's definitely some compute overhead compared to async, but we save so much developer time having effortless concurrency and never being worried that, say, using a slow third-party API over the web will slow down other requests.
- ddorian43 4y agoSome comments on the page says gevent is actually faster than async.
- harpiaharpyja 4y agoI don't know why curio hasn't seen greater adoption. Having used both, it seems superior to asyncio in most respects.
- amelius 4y agoAsync programming is Windows 3.1 style cooperative multitasking.
- cturner 4y agoDifferent trade-offs. It is much easier to pursue cache-efficiency in a cooperative multitasking setting than with preempt threads.
- samsquire 4y agoI hope to learn how to use async code more effectively. Coroutines are very interesting. Structured concurrency is very useful in defining understanding concurrency. I wrote a multithreaded userspace scheduler in Java C and Rust which multiplexes lightweight threads over kernel threads. It is a 1:M:N scheduler with 1 scheduler threads M kernel threads and N lightweight threads. This is similar to golang which is P:M:N https://GitHub.com/samsquire/preemptible-thread https://GitHub.com/samsquire/preemptible-thread I am deeply interested in parallel and asychronous code. I write about it on my journal (link in my profile) I am curious if anybody has any ideas on how you would build an interpreter that is multithreaded - with each interpreter running in its own thread and sending objects between threads is done without copying or marshalling. I I think Java does it but I am yet to ask how it does it. Maybe I'll ask Stackoverflow. I wrote a parallel imaginary assembly interpreter that is backed by an actor framework which can send and receive messages in mailboxes. Here's some code: threads 25 <start> mailbox numbers mailbox methods set running 1 set current_thread 0 set received_value 0 set current 1 set increment 1 :while1 while running :end receive numbers received_value :send receivecode methods :send :send :send add received_value current addv current_thread 1 modulo current_thread 25 send numbers current_thread increment :while1 sendcode methods current_thread :print endwhile :while1 jump :end :print println current return :end This is 25 threads that each send integers to eachother as fast as they can. The sendcode instruction can cause the other thread to run some code. It can get up to 1.7 million requests per second without the sendcode and receivecode. With method sending it gets ~600,000 requests per second
- aivarsk 4y agoA must-read before diving into asyncio: Async Python is slower than "sync" Python under a realistic benchmark. A bigger worry is that async frameworks go a bit wobbly under load. https://calpaterson.com/async-python-is-not-faster.html https://calpaterson.com/async-python-is-not-faster.html
- postultimate 4y agoNo subinterpreters in 3.11 ? If we had those, all this async idiocy would go away, no more code colours, no more single-core, even better isolation and protection against context-switching tangles. (the implementation not so nice though. Python threads on machine threads ? Whose stupid idea was that ?)