场景
多请求前后到达,对时效性要求高,就要上异步了。这时要考虑异步使用协程快、还是线程快。写了脚本测试一下。
python 自带的time.sleep存在的问题
从图片中结果可以看出,time.sleep自身就存在耗时,调用一次约增加耗时10ms左右。
测试结果和代码
from time import sleep, time_ns
from threading import Thread
import gevent
from gevent import monkey
# monkey.patch_all()
time_list = []
def do_request(start_ts):
sleep(0.05) # 模拟请求io 50ms
time_list.append(time_ns() - start_ts)
def do_request_g(start_ts):
gevent.sleep(0.05) # 模拟请求io 50ms
time_list.append(time_ns() - start_ts)
if __name__ == '__main__':
# start = time_ns()
# sleep(0.05)
# end = time_ns()
# print('sleep', (end - start) * 0.000001)
# 同步请求测试
for i in range(100):
# 每轮次模拟2个请求任务前后到达
now_ts = time_ns()
do_request(now_ts)
do_request(now_ts)
sleep(0.1)
print('同步平均耗时(非异步,理论最慢)', sum(time_list) / len(time_list) * 0.000001)
# 真异步请求测试
do_request(time_ns())
do_request(time_ns())
do_request(time_ns())
do_request(time_ns())
do_request(time_ns())
do_request(time_ns())
do_request(time_ns())
do_request(time_ns())
do_request(time_ns())
do_request(time_ns())
print('真异步平均耗时(理论最快)', sum(time_list) / len(time_list) * 0.000001)
# 多线程异步请求测试
for i in range(100):
# 每轮次模拟2个请求任务前后到达
now_ts = time_ns()
t1 = Thread(target=do_request, args=(now_ts, ))
t1.start()
t2 = Thread(target=do_request, args=(now_ts, ))
t2.start()
sleep(0.1)
sleep(50)
print('线程异步平均耗时', sum(time_list) / len(time_list) * 0.000001)
# 协程异步请求测试
for i in range(100):
# 每轮次模拟 2个请求任务 前后到达
now_ts = time_ns()
s1 = gevent.spawn(do_request_g, now_ts)
s1.start()
s2 = gevent.spawn(do_request_g, now_ts)
s2.start()
gevent.sleep(0.1)
gevent.sleep(50)
print('协程异步平均耗时', sum(time_list) / len(time_list) * 0.000001)
从结果来看,该场景下采用起线程实现异步是更优的。但目前考虑方式都是来了任务才起线程或协程,还有其他方式,比如可以先起好几个做任务的线程,然后通过队列的方式传递任务等,先留个坑。