Ich habe ein Problem mit meiner API und hoffe, dass mir jemand helfen kann. Trotz der Hinzufügung von Multithreading liegen die Leistungssteigerungen weit hinter meinen Erwartungen zurück. Wenn ein Thread 1 Sekunde benötigt, um eine Aufgabe abzuschließen, sollten im Idealfall 10 Threads, die gleichzeitig ausgeführt werden, ebenfalls etwa 1 Sekunde dauern (so mein Verständnis). Allerdings sind meine API-Antwortzeiten immer noch sehr langsam.
Ich verwende FastAPI zusammen mit Bibliotheken wie Playwright, MongoDB und ThreadPoolExecutor. Das Ziel bestand darin, Threading für CPU-gebundene Aufgaben und Async-Await für IO-gebundene Aufgaben zu verwenden. Dennoch verbessern sich meine Reaktionszeiten nicht wie erwartet.
Ein Teil meines Projekts besteht darin, Buchabfragen mithilfe von Playwright zu automatisieren, um mit einem EPUB-Viewer zu interagieren. Die folgende Funktion verwendet Playwright, um einen Browser zu öffnen, zur Seite eines Buches zu navigieren und Suchvorgänge durchzuführen:
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
Die obige Funktion soll asynchron sein, um das Blockieren anderer Aufgaben zu vermeiden. Allerdings ist die Leistung selbst mit diesem asynchronen Setup immer noch nicht wie erwartet.
Hinweis: Ich habe berechnet, dass es etwa 0,0028 Sekunden dauert, ein Buch zu öffnen und ein einzelnes Buch abzufragen
Ich habe run_in_executor() verwendet, um Funktionen in ProcessPoolExecutor auszuführen und dabei versucht, die GIL zu vermeiden und Arbeitslasten richtig zu verwalten.
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
Selbst nach diesen Änderungen ist meine API immer noch langsam. Was fehlt mir? Hat jemand ähnliche Probleme mit Pythons GIL-, Threading- oder asynchronen Setups gehabt? Für jeden Rat wäre ich sehr dankbar!
Das obige ist der detaillierte Inhalt vonWarum ist meine Multithread-API immer noch langsam?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!