ASYNCIO

  • Concurrency is like having two threads running on a single core CPU. Instructions from each thread could be interleaved, but at any given time, only one of the two threads is actively making progress.

 

  • Parallelism is like having two threads running simultaneously on different cores of a multi-core CPU.

Asynchronous programming

Asynchronous programming is a means of programming in which a unit of work runs separately from the main application thread and notifies the calling thread of its completion, failure or progress.​

Why asynchronous programming?

Why do we want to write asynchronous programs you say — because it could increase the performance of your program many many times. Imagine you have a single core machine you are running your app on. You receive a request, and you need to make two database queries to fulfil that request. Each query takes 50ms of time. With a synchronous program, you would make the second request only after completing the first — total time 100ms. With an asynchronous program, you could fire off both the queries one after the other — total time 50ms.

asyncio

  • Event loop
  • Tasks and Coroutines

The Event Loop

It runs tasks one after the other. At any given time, only one of the tasks is running.

As you can imagine, there is a lot of pressure on the active task, since other tasks are waiting for their turn. So, when the active task makes a blocking call, say a network request, and cannot make further progress it gives the control back to the event loop realizing that some other task could possibly better utilize the event loop’s time. It also tells the event loop what exactly it is blocked upon, so that when the network response comes, the event loop can consider giving it time to run again.

 Coroutine & Task

Coroutines (co-operative routines) are a key element of the symphony. It is the coroutines, and their co-operative nature, that enables giving up control of the event loop, when the coroutine has nothing useful to do. A coroutine is a stateful generalisation of the concept of subroutine.

when a coroutine “returns” (yields control) it simply means that it has paused its execution (with some saved state). So when you “invoke” (give control to) the coroutine subsequently, it would be correct to say that the coroutine has resumed its execution

  • In Python 3.5+, the way a coroutine pauses itself is using the await keyword. Inside a coroutine, when you await on another coroutine, you step off the event loop and schedule the awaited coroutine to run immediately. That is, an await other_coroutine inside a coroutine will pause it, and schedule the coroutine other_coroutine to run immediately.
import asyncio


async def foo():
    print('Running in foo')
    await asyncio.sleep(0)
    print('Explicit context switch to foo again')


async def bar():
    print('Explicit context to bar')
    await asyncio.sleep(0)
    print('Implicit context switch back to bar')


async def main():
    tasks = [foo(), bar()]
    await asyncio.gather(*tasks)


asyncio.run(main())

ASYNCIO

By Abhyuday Pratap Singh