FastAPI中run_in_threadpool与run_in_executor性能差异问询
FastAPI并发测试中的性能异常问题
我使用ApacheBench(ab)对FastAPI应用发送多请求进行性能测试,命令如下:
ab -n 1000 -c 50 -H 'accept: application/json' -H 'x-data-origin: source' 'http://localhost:8001/test/async'
原始FastAPI应用代码
import time import asyncio import enum from typing import Any from fastapi import FastAPI, Path, Body from starlette.concurrency import run_in_threadpool app = FastAPI() loop = asyncio.get_running_loop() def sync_func() -> None: time.sleep(3) print("sync func") async def sync_async_with_fastapi_thread() -> None: await run_in_threadpool(time.sleep, 3) print("sync async with fastapi thread") async def sync_async_func() -> None: await loop.run_in_executor(None, time.sleep, 3) async def async_func() -> Any: await asyncio.sleep(3) print("async func") @app.get("/test/sync") def test_sync() -> None: sync_func() print("sync") @app.get("/test/async") async def test_async() -> None: await async_func() print("async") @app.get("/test/sync_async") async def test_sync_async() -> None: await sync_async_func() print("sync async") @app.get("/test/sync_async_fastapi") async def test_sync_async_with_fastapi_thread() -> None: await sync_async_with_fastapi_thread() print("sync async with fastapi thread")
ApacheBench测试结果
async(使用asyncio.sleep):
并发级别:50- 测试耗时:63.528秒
- 完成请求数:1000
- 失败请求数:0
- 总传输量:128000字节
- HTML传输量:4000字节
- 每秒请求数:15.74次(均值)
- 单请求耗时:3176.407毫秒(均值)
- 单请求耗时(所有并发请求均值):63.528毫秒
- 接收传输速率:1.97千字节/秒
sync(使用time.sleep):
并发级别:50- 测试耗时:78.615秒
- 完成请求数:1000
- 失败请求数:0
- 总传输量:128000字节
- HTML传输量:4000字节
- 每秒请求数:12.72次(均值)
- 单请求耗时:3930.751毫秒(均值)
- 单请求耗时(所有并发请求均值):78.615毫秒
- 接收传输速率:1.59千字节/秒
sync_async(使用run_in_executor执行time.sleep):
并发级别:50- 测试耗时:256.201秒
- 完成请求数:1000
- 失败请求数:0
- 总传输量:128000字节
- HTML传输量:4000字节
- 每秒请求数:3.90次(均值)
- 单请求耗时:12810.038毫秒(均值)
- 单请求耗时(所有并发请求均值):256.201毫秒
- 接收传输速率:0.49千字节/秒
sync_async_fastapi(使用run_in_threadpool执行time.sleep):
并发级别:50- 测试耗时:78.877秒
- 完成请求数:1000
- 失败请求数:0
- 总传输量:128000字节
- HTML传输量:4000字节
- 每秒请求数:12.68次(均值)
- 单请求耗时:3943.841毫秒(均值)
- 单请求耗时(所有并发请求均值):78.877毫秒
- 接收传输速率:1.58千字节/秒
测试结果存在显著差异,尤其是使用run_in_executor时,平均单请求耗时高达12秒,无法理解该现象的原因。
编辑更新:优化后的代码
根据建议优化后的代码如下:
import time import asyncio from concurrent.futures import ThreadPoolExecutor from anyio import to_thread from starlette.concurrency import run_in_threadpool from fastapi import FastAPI from typing import Any to_thread.current_default_thread_limiter().total_tokens = 200 loop = asyncio.get_running_loop() executor = ThreadPoolExecutor(max_workers=100) def sync_func() -> None: time.sleep(3) print("sync func") async def sync_async_with_fastapi_thread() -> None: await run_in_threadpool(time.sleep, 3) print("sync async with fastapi thread") async def sync_async_func() -> None: await loop.run_in_executor(executor, time.sleep, 3) async def async_func() -> Any: await asyncio.sleep(3) print("async func") app = FastAPI() @app.get("/test/sync") def test_sync() -> None: sync_func() print("sync") @app.get("/test/async") async def test_async() -> None: await async_func() print("async") @app.get("/test/sync_async") async def test_sync_async() -> None: await sync_async_func() print("sync async") @app.get("/test/sync_async_fastapi") async def test_sync_async_with_fastapi_thread() -> None: await sync_async_with_fastapi_thread() print("sync async with fastapi thread")
内容的提问来源于Stack Exchange,提问作者Raphael Obadia
相关产品推荐
相关产品推荐

