It's well known that asyncio is designed to speed up server ,enhance it's ability to carry up more requests as a web server. However according to my test today, I shockedly found that for the puropse of switching between tasks ,using Thread is much more faster than using coroutine (eventhough under a thread lock as guarantee). Is that means it meaningless using coroutine?
Wondering why ,could anyone please help me figure out?
Here's my testting code : add a global variable 2 000 000 times in two tasks by turns.
from threading import Thread , Lock import time , asyncio def thread_speed_test(): def add1(): nonlocal count for i in range(single_test_num): mutex.acquire() count += 1 mutex.release() mutex = Lock() count = 0 thread_list = list() for i in range(thread_num): thread_list.append(Thread(target = add1)) st_time = time.time() for thr in thread_list: thr.start() for thr in thread_list: thr.join() ed_time = time.time() print("runtime" , count) print(f'threading finished in {round(ed_time - st_time,4)}s ,speed {round(single_test_num * thread_num / (ed_time - st_time),4)}q/s' ,end='\n\n') def asyncio_speed_test(): count = 0 @asyncio.coroutine def switch(): yield async def add1(): nonlocal count for i in range(single_test_num): count += 1 await switch() async def main(): tasks = asyncio.gather( *(add1() for i in range(thread_num)) ) st_time = time.time() await tasks ed_time = time.time() print("runtime" , count) print(f'asyncio finished in {round(ed_time - st_time,4)}s ,speed {round(single_test_num * thread_num / (ed_time - st_time),4)}q/s') asyncio.run(main()) if __name__ == "__main__": single_test_num = 1000000 thread_num = 2 thread_speed_test() asyncio_speed_test() got the following result in my pc:
2000000 threading finished in 0.9332s ,speed 2143159.1985q/s 2000000 asyncio finished in 16.044s ,speed 124657.3379q/s append:
I realized that when thread number increase , threading mode goes slower but async mode goes faster. here's my test results:
# asyncio # thread_num numbers of switching in 1sec average time of a single switch(ns) 2 122296 8176 32 243502 4106 128 252571 3959 512 253258 3948 4096 239334 4178 # threading # thread_num numbers of switching in 1sec average time of a single switch(ns) 2 2278386 438 4 737829 1350 8 393786 2539 16 367123 2720 32 369260 2708 64 381061 2624 512 381403 2622
await switch()for? It seems to slow down asyncio. Results with that like commented: runtime 2000000 threading finished in 4.0422s ,speed 494785.7794q/s runtime 2000000 asyncio finished in 0.1093s ,speed 18302989.839q/s