最近学习 aiohttp 。
想试试 python motor 单条插入的总体时间。没想到需要 160 多秒。 如果用 pymongo 单条插入,不用 aiohttp 和 motor,总体时间只需要 23 秒。如果用 insert_many,总体时间只需要 1.4 秒
请问各位大佬,是我 aiohttp 或者 motor 做错了什么?
import asyncio,hashlib,time
from aiohttp import web
import motor.motor_asyncio
motor_mongo_client = motor.motor_asyncio.AsyncIOMotorClient('127.0.0.1', 17177)
async def mongodb_test(request):
start_time = time.time()
for i in range(100000):
md5 = str(i) + u'a9cfb75778b38676'
md5 = md5.encode('utf-8')
md5 = hashlib.md5(md5).hexdigest()
items = {
'md5': md5,
'i': i
}
try:
await motor_mongo_client['mongodb_test']['insert_test'].insert_one(items)
except Exception as e:
print(e)
continue
end_time = time.time()
const_time = end_time - start_time
print(const_time)
return web.Response(text="done")
loop = asyncio.get_event_loop()
app = web.Application(loop=loop)
app.add_routes([
web.get('/index', index),
web.get('/mongodb_test',mongodb_test),
])
web.run_app(app, host='127.0.0.1', port=8080)
1
sivacohan 2020-09-01 11:21:56 +08:00 1
切换上下文是有成本的。
await motor_mongo_client['mongodb_test']['insert_test'].insert_one(items) 这一句会导致每一次执行到这,都会切换一下上下文。所以导致会慢。 异步操作一般解决的是 IO 慢,导致整体并发不足的情况。在你的例子里,数据库 IO 并不是瓶颈,这个例子里,你应该使用多线程、或多进程。 |
2
linw1995 2020-09-01 13:23:28 +08:00 1
motor 实际就是 pymongo + 多线程,每次操作都要另外个线程去做,完成再回调到主线程。而直接用 pymongo 就是单个线程在跑,少了上下文切换,当然快啦。并发高速度慢,并发低速度快,根据业务情况取舍吧
|
3
bnm965321 2020-09-01 13:27:05 +08:00 1
可以直接 ensure_future 还是什么函数,把协程插入到事件循环就行不要让下一个协程等待上一个执行完毕
|
4
676529483 2020-09-01 15:58:18 +08:00 1
你 for 循环里面用 await 就变成单线程了,试试 create_task
|
5
Wincer 2020-09-01 18:59:12 +08:00 1
operations = []
for 循环内部 await 改成: operations.append(motor_mongo_client['mongodb_test']['insert_test'].insert_one(items)) 然后 asyncio.gather(*operations),这才是正确的使用方法 |