Live data from Hacker News

Asynchronous programming and cooperative multitasking

luminousmen.com

11–20 of 26 posts

Re: Asynchronous programming and cooperative multitasking

#11

Good job at highlighting async as being cooperative multi-tasking. Those of us old enough will remember the fanfare when both Mac and Windows moved from cooperative to pre-emptive multi-tasking models. To adapt a well known phrase, every non-trivial cooperative application includes a half-baked, buggy implementation of a pre-emptive scheduler. We know that pre-emptive scheduling of isolated processes is a good abstra…

Cooperative multi-tasking if terrible is you don't have control over what the others are doing, but in your program you generally do.

It also have the benefit of making concurrent access much easier to reason about without having to resort to message passing or immutability, yet locks are rarely necessary.

As usual, it's a trade off.

Re: Asynchronous programming and cooperative multitasking

#12

On a related note, I found that asyncio (cooperative multitasking in Python) has made huge strides in usability in Python 3.7. The code feels sequential, and it’s quite easy to understand the flow of events ; it’s very explicit yet you never have to run the callbacks yourself, the exceptions do show up, and you don’t even need to manipulate a `loop` object anymore! If you're trying to learn how to use it, my advice w…

I agree, and the docs got better too. In 3.7, asyncio is usable for people that don't understand it very well. Before that, you had to learn the whole thing brick by brick before being able to do something serious. Yet, there is a missing piece I'm hoping we'll see in 3.8: a way to limit the scope of `asyncio.ensure_future()`. Indeed, right now either you `await` to get a sequential execution , or you call `asyncio.e…

> So the best practice is to use `asyncio.gather()` to delimitate the pyramid of the task life cycle. Unfortunatly few people kow this, and hence do it.

And even then, any async function might run `loop = asyncio.get_event_loop()`, run some background processes, and return before they stopped! I actually had this exact problem with my realtime sensor data server: the background tasks were never properly closed, and the sockets remained open.

The article you linked to (https://vorpus.org/blog/notes-on-structured-concurrency-or-g...) is super interesting. I didn't get the appeal of `trio` before, but now it does seem really useful.

Re: Asynchronous programming and cooperative multitasking

#13

Good job at highlighting async as being cooperative multi-tasking. Those of us old enough will remember the fanfare when both Mac and Windows moved from cooperative to pre-emptive multi-tasking models. To adapt a well known phrase, every non-trivial cooperative application includes a half-baked, buggy implementation of a pre-emptive scheduler. We know that pre-emptive scheduling of isolated processes is a good abstra…

Can't agree more. As someone who've done lots of work on both preemptive- and cooperative- multitasking codebases I'm perplexed by how many frameworks dive head-first into the latter.

Re: Asynchronous programming and cooperative multitasking

#15
I think one distinction often missed is if the programming language can share memory between threads natively (without copying) and if the language has stable nio & concurrency libraries to do this today on a live service. The only bottleneck we have is CPU, and because of litography/memory bandwidth it will never go away for transistor processors. I just called this "joint parallel" for my completely async. non-blocking HTTP server/client; meaning it can have many cores work "simultaneously" on the same memory, which is really rare in the async. world.

Re: Asynchronous programming and cooperative multitasking

#16

Good job at highlighting async as being cooperative multi-tasking. Those of us old enough will remember the fanfare when both Mac and Windows moved from cooperative to pre-emptive multi-tasking models. To adapt a well known phrase, every non-trivial cooperative application includes a half-baked, buggy implementation of a pre-emptive scheduler. We know that pre-emptive scheduling of isolated processes is a good abstra…

> I've said before and I'll say again: this kind of async is a design flaw. It's a retrograde step that brings all the cognitive overload of cooperative multitasking back.

You seem to be assuming that preemption is always needed or wanted. This is not always the case. The lack of preemption actually simplifies a number of factors that simply aren't relevant in async scenarios in a single program.

async/await patterns are actually the perfect solution for capturing the minimal context necessary for resumption after the async operation completes.

Re: Asynchronous programming and cooperative multitasking

#17

Good job at highlighting async as being cooperative multi-tasking. Those of us old enough will remember the fanfare when both Mac and Windows moved from cooperative to pre-emptive multi-tasking models. To adapt a well known phrase, every non-trivial cooperative application includes a half-baked, buggy implementation of a pre-emptive scheduler. We know that pre-emptive scheduling of isolated processes is a good abstra…

I'm currently working on a project that's implementing this whole pattern using AWS. 1.) Requests are written to a DynamoDB table 2.) a Lambda subscribes to the Dynamo event stream 3.) each event from the stream causes the Lambda to make an async call to an external system 4.) A message (with a delay) is sent to SQS from the Lambda that the async call has been made 5.) Another Lambda reads from the SQS queue and updates the original DynamoDB record completing the loop.

The delay in the queue simulates a polling interval to the external system and when a successful response is returned from the external system the Dynamo record is updated with a status telling the Lambda subscribing to the event stream that "the loop" is done.

This setup has to run at fairly significant peak loads and we're relying on Amazon to provision resources reliably enough to pull this off. None of us know if this will work but in terms of abstracting away the complexities of async/concurrent processing it's a novel approach.

Re: Asynchronous programming and cooperative multitasking

#18
The interesting linked article reminds me that techniques (crutches?) popular in the embedded world still seem fresh and new to the rest of the computing community.

A scheduler need not be complex - a superloop / commutator / for (;;) {} construction that polls clients and workers is usually enough to provide the appearance of a preemptive multitasker. The complexities typically arise in communicating data from interrupt contexts back to the foreground thread, and from appropriately designing the elements to deal with exceptions, but these complexities are already familiar to anyone developing non-trivial products whether or not a preemptive switcher is around.

Re: Asynchronous programming and cooperative multitasking

#19

Good job at highlighting async as being cooperative multi-tasking. Those of us old enough will remember the fanfare when both Mac and Windows moved from cooperative to pre-emptive multi-tasking models. To adapt a well known phrase, every non-trivial cooperative application includes a half-baked, buggy implementation of a pre-emptive scheduler. We know that pre-emptive scheduling of isolated processes is a good abstra…

I've been doing cooperative multitasking using dataflow for a couple of decades; your terms are fuzzy enough that you're criticizing the problems of particular implementations and not fundamental flaws in the concepts.

As an example of cooperative multitasking with dataflow, consider single-process nginx. Events are delivered using epoll; nginx has an event loop that does work on the next task that has data ready (or a timer event.) This is called the Reactor Pattern in the article.

Re: Asynchronous programming and cooperative multitasking

#20

This is written from a closed (python) world perspective. Even in python you have other alternatives (stackless [0]). In statically typed functional programming languages, the monadic approach (still) is rather popular: f () >>= g can be read as follows, when (eventually) the function f produces a result, hand that result as an argument to the function g. Monads do have a cognitive overhead, but the type system preve…

Even in the python async/await world, you can get preemptable multitasking by adding in a few ProcessPoolExecutor threads. I've found this to be extremely effective in a web crawler: the main thread is 100% cooperative and does all of the network I/O on a single core, while cpu-hungry activities like webpage parsing are done by ProcessPoolExecutor processes on other cores. The code is pretty and I can fully use an entire server with what is conceptually a single crawler.

asyncio.create_subprocess_shell() is another way to get a preemptable thing in the Python async/await world.

Post reply on HN