Настройка:
- Версия FastAPI: 0.95.1
- Версия SQLAlchemy: 2.0.19
- База данных: SQLite
- Версия PyNest: 0.1.0
- Асинхронная версия: ~500 секунд для 1000 запросов
- Синхронная версия: 0,72 секунды на 1000 запросов
Код: Выделить всё
class Config:
def __init__(self):
self.engine = create_async_engine("sqlite+aiosqlite:///finance.db", connect_args={"check_same_thread": False})
self.SessionLocal = async_sessionmaker(self.engine)
self.Base = Base
async def create_all(self):
async with self.engine.begin() as conn:
await conn.run_sync(self.Base.metadata.create_all)
async def drop_all(self):
async with self.engine.begin() as conn:
await conn.run_sync(self.Base.metadata.drop_all)
async def get_db(self):
db = self.SessionLocal()
try:
yield db
finally:
await db.close()
Код: Выделить всё
class OrmService:
def __init__(self, db_type: str = "postgresql", config_params: dict = None):
self.Base = declarative_base()
self.config = ConfigFactory(db_type=db_type).get_config()
self.config_url = self.config(**config_params).get_engine_url()
self.engine = create_engine(self.config_url)
def create_all(self):
self.Base.metadata.create_all(bind=self.engine)
def drop_all(self):
self.Base.metadata.drop_all(bind=self.engine)
def get_db(self) -> Session:
try:
session = sessionmaker(bind=self.engine)
return session()
except Exception as e:
raise e
Код: Выделить всё
@Controller("finance")
class FinanceController:
@Get("/transactions")
async def get_transactions(self, session: AsyncSession = Depends(config.get_db)):
stmt = select(Transaction)
query = await session.execute(stmt)
return query.scalars().all()
Код: Выделить всё
@Controller("transaction", prefix="transaction")
class TransactionController:
service: TransactionService = Depends(TransactionService)
@Get("/")
def get_transactions(self):
return self.service.get_transactions()
@lru_cache()
class TransactionService:
def __init__(self):
self.orm_config = config
self.session = self.orm_config.get_db()
def get_transactions(self):
return self.session.query(TransactionEntity).first()
Я использую следующий тестовый сценарий для отправки 1000 запросов к обеим версиям:
Код: Выделить всё
import asyncio
import aiohttp
import time
async def fetch(session, url):
start_time = time.time()
async with session.get(url) as response:
response_text = await response.text()
end_time = time.time()
print(f"URL: {url} - Start: {start_time:.2f}, End: {end_time:.2f}, Duration: {end_time - start_time:.2f} seconds")
return response_text
async def main():
s = time.time()
urls = ["http://0.0.0.0:8088/transactions"] * 1000
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for url in urls]
responses = await asyncio.gather(*tasks)
print(len(responses))
print("response have been gathered")
print(f"Total time: {time.time() - s:.2f}")
# Run the main coroutine
asyncio.run(main())
Меня озадачивает огромная разница в производительности между двумя версиями. Асинхронная версия, от которой я ожидал большей производительности или, по крайней мере, сопоставимой по производительности, оказалась значительно медленнее. Что может быть причиной такого несоответствия в производительности между синхронной и асинхронной версиями одного и того же приложения?
Будем очень признательны за любые идеи или предложения о том, что может способствовать этой проблеме и как оптимизировать асинхронную версию.
Подробнее здесь: https://stackoverflow.com/questions/775 ... in-fastapi
Мобильная версия