Skip to content

Instantly share code, notes, and snippets.

@Tes3awy
Forked from ipwnponies/asyncio.md
Created November 2, 2021 05:15
Show Gist options
  • Save Tes3awy/77db726c861f62ee9d5d500f74713f48 to your computer and use it in GitHub Desktop.
Save Tes3awy/77db726c861f62ee9d5d500f74713f48 to your computer and use it in GitHub Desktop.
concurrent.futures (threading) vs. asyncio (event loop)

Summary

This gist demonstrates the difference between threading and asyncio. To be clear, they're both limited by the Global Interpreter Lock and are both single process, multi-threaded. They are both forms of concurrency but not parallelism.

Threading, via concurrent.futures

Threading (via Thread, concurrent.futures) employs time-slicing of CPU. All threads are given a slot of CPU time to do work. If the thread is blocking (sleeping or blocked on sockets), then off it goes to the next thread. With many threads that are blocked for long periods, this begins to degrade into polling (polling vs. interrupt)

asyncio

asyncio uses an event loop and is more akin to a pub-sub, push notification model. Threads will announce they're blocked by using asyncio methods. The next available thread at the top of the queue is then processed on, until it completes or is blocked again. This has reduced concurrency and can allow one thread to starve out the others. If the access pattern is threads that are blocked for long time, this model will ensure that you don't bother checking a thread, you wait for it to announce it's available.

from concurrent.futures import ThreadPoolExecutor
from time import sleep
def return_after_5_secs(message, time=2):
print('Stariting {}'.format(message))
sleep(time)
print('Fisnihed {}'.format(message))
return message
def concurrent_test():
pool = ThreadPoolExecutor(3)
¦
future = pool.submit(return_after_5_secs, "hello", 5)
future1 = pool.submit(return_after_5_secs, "world", 2)
sleep(5)
print(future.result())
print(future1.result())
# Comment out asyncio import for testing threads, it will mess with threading
import asyncio
import datetime
import random
async def display_date(num, time):
print("Starting Loop: {} Time: {}".format(num, datetime.datetime.now().time()))
# time = random.randint(3, 5)
print('PRocessing.... taking {} seconds'.format(time))
sleep(2)
print('Took 2 seconds of processing, now blocking on io {}'.format(datetime.datetime.now().time()))
await asyncio.sleep(time)
print('Finsihed loop {loop} {time}'.format(time=datetime.datetime.now().time(), loop=num))
# await my_sleep_func(time)
def asyncio_test():
loop = asyncio.get_event_loop()
asyncio.ensure_future(display_date(1, 10))
asyncio.ensure_future(display_date(2, 5))
loop.run_forever()
if __name__ == '__main__':
# concurrent_test()
asyncio_test()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment