Maison >développement back-end >Tutoriel Python >Pourquoi mon API multithread est-elle toujours lente ?
Je suis confronté à un problème avec mon API et j'espère que quelqu'un pourra m'aider. Malgré l'ajout du multi-threading, les gains de performances sont loin de ce à quoi je m'attendais. Idéalement, si un thread prend 1 seconde pour terminer une tâche, alors 10 threads exécutés simultanément devraient également prendre environ 1 seconde (c'est ce que je comprends). Cependant, mes temps de réponse API sont encore très lents.
J'utilise FastAPI avec des bibliothèques comme Playwright, MongoDB et ThreadPoolExecutor. L'objectif était d'utiliser le threading pour les tâches liées au processeur et l'attente asynchrone pour les tâches liées aux E/S. Pourtant, mes temps de réponse ne s’améliorent pas comme prévu.
Une partie de mon projet consiste à automatiser les requêtes de livres à l'aide de Playwright pour interagir avec une visionneuse EPUB. La fonction suivante utilise Playwright pour ouvrir un navigateur, accéder à la page d'un livre et effectuer des recherches :
from playwright.async_api import async_playwright import asyncio async def search_with_playwright(search_text: str, book_id: str): async with async_playwright() as p: browser = await p.chromium.launch(headless=True) page = await browser.new_page() book_id = book_id.replace("-1", "") book_url = f"http://localhost:8002/book/{book_id}" await page.goto(book_url) await page.fill("#searchInput", search_text) await page.click("#searchButton") await page.wait_for_selector("#searchResults") search_results = await page.evaluate(''' () => { let results = []; document.querySelectorAll("#searchResults ul li").forEach(item => { let excerptElement = item.querySelector("strong:nth-of-type(1)"); let cfiElement = item.querySelector("strong:nth-of-type(2)"); if (excerptElement && cfiElement) { let excerpt = excerptElement.nextSibling ? excerptElement.nextSibling.nodeValue.trim() : ""; let cfi = cfiElement.nextSibling ? cfiElement.nextSibling.nodeValue.trim() : ""; results.push({ excerpt, cfi }); } }); return results; } ''') await browser.close() return search_results
La fonction ci-dessus est censée être asynchrone pour éviter de bloquer d'autres tâches. Cependant, même avec cette configuration asynchrone, les performances ne sont toujours pas celles attendues.
Remarque : j'ai calculé que le temps nécessaire pour ouvrir un livre et exécuter une requête sur un seul livre est d'environ 0,0028 s
J'ai utilisé run_in_executor() pour exécuter des fonctions dans ProcessPoolExecutor, en essayant d'éviter le GIL et de gérer correctement les charges de travail.
async def query_mongo(query: str, id: str): query_vector = generate_embedding(query) results = db[id].aggregate([ { "$vectorSearch": { "queryVector": query_vector, "path": "embedding", "numCandidates": 2100, "limit": 50, "index": id } } ]) # Helper function for processing each document def process_document(document): try: chunk = document["chunk"] chapter = document["chapter"] number = document["chapter_number"] book_id = id results = asyncio.run(search_with_playwright(chunk, book_id)) return { "content": chunk, "chapter": chapter, "number": number, "results": results, } except Exception as e: print(f"Error processing document: {e}") return None # Using ThreadPoolExecutor for concurrency all_data = [] with ThreadPoolExecutor() as executor: futures = {executor.submit(process_document, doc): doc for doc in results} for future in as_completed(futures): try: result = future.result() if result: # Append result if it's not None all_data.append(result) except Exception as e: print(f"Error in future processing: {e}") return all_data
Même après ces changements, mon API est toujours lente. Qu'est-ce qui me manque ? Quelqu'un a-t-il rencontré des problèmes similaires avec les configurations GIL, threading ou asynchrone de Python ? Tout conseil serait grandement apprécié !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!