一直听闻 fastapi 速度比 flask 快,作为异步框架比flask要快,甚至能比肩 node.js 与 go ,所以想测试一下,故有以上测试记录。
从结果来看 fastapi 确实要比 flask 快,但是也有一些让人困惑的点,部分相关测试的代码将在文末提供。
- 异步代码的提升并不是很高,httpx 的异步代码反而比同步代码要慢不少
- 异步代码在多个 worker 的情况下,除了 sleep 测试,均比不上同步代码
- 使用多个 worker 提升并不明显,在 httpx 连接测试中,使用 2 个worker 可以提升 1 倍,但再提升到 4 个时效率增加不明显
- hypercorn 使用 uvloop 工作类时,httpx 连接测试提升明显,但是 sql 和 sleep 测试反而变慢了不少
- 还有一个重要的发现,如果在同步代码的函数前加
async
即async def xxx():
,反而会使响应变的超慢(服务器会只能处理完一个请求,再开始处理下一个请求),所以是同步代码的路由函数不应加async
标志。【注:这个结论测试数据并未在上图中显示出,是当前补充的】
部分测试代码如下:
SQL 测试
同步代码
@app.get("/sql")
def sql_get(*, ses: Session = Depends(get_session), req: Request):
t1 = time.time()
statement = select(func.count()).select_from(Test).where(Test.cname.contains('XX'))
# statement = select(Test).where(Test.id.startswith('a')).limit(1)
result = ses.exec(statement)
return [result.all(), time.time() - t1, str(req.url)]
异步代码
@app.get("/sql")
async def sql_get(*, ses: AsyncSession = Depends(get_session), req: Request):
t1 = time.time()
statement = select(func.count()).select_from(Test).where(Test.cname.contains('XX'))
# statement = select(Test).where(Test.id.startswith('a')).limit(1)
result = await ses.exec(statement)
return [result.all(), time.time() - t1, str(req.url)]
httpx 测试
同步代码
@app.get("/http")
def http_get(*, client: httpx.Client = Depends(get_httpx_client), req: Request):
t1 = time.time()
response = client.get('https://example.com')
return [response.text, time.time() - t1, str(req.url)]
异步代码
@app.get("/http")
async def http_get(*, client: httpx.AsyncClient = Depends(get_httpx_client), req: Request):
t1 = time.time()
response = await client.get('https://example.com')
return [response.text, time.time() - t1, str(req.url)]
sleep 测试
同步代码
@app.get("/time")
def time_get(*, req: Request):
t1 = time.time()
time.sleep(2)
return [time.time() - t1, str(req.url)]
异步代码
@app.get("/time")
async def time_get(*, req: Request):
t1 = time.time()
await asyncio.sleep(2)
return [time.time() - t1, str(req.url)]