我的 API 遇到問題,希望有人可以幫忙。儘管添加了多線程,但效能提升遠沒有達到我的預期。理想情況下,如果一個執行緒需要 1 秒鐘來完成一項任務,那麼並發運行的 10 個執行緒也應該需要大約 1 秒鐘(這是我的理解)。然而,我的 API 回應時間仍然很慢。
我正在使用 FastAPI 以及 Playwright、MongoDB 和 ThreadPoolExecutor 等函式庫。目標是對 CPU 密集型任務使用線程,對 IO 密集型任務使用非同步等待。儘管如此,我的回應時間並沒有像預期的那樣改善。
我的專案的一部分涉及使用 Playwright 與 EPUB 檢視器互動來自動進行圖書查詢。以下函數使用 Playwright 開啟瀏覽器、導航至書籍頁面並執行搜尋:
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
上面的函數是非同步的,以避免阻塞其他任務。然而,即使採用這種非同步設置,性能仍然達不到預期。
注意:我計算過單本書開啟書籍和執行查詢所需的時間約為 0.0028s
我使用 run_in_executor() 來執行 ProcessPoolExecutor 中的函數,試圖避免 GIL 並正確管理工作負載。
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
即使在這些變更之後,我的 API 仍然很慢。我缺什麼?有人在 Python 的 GIL、線程或非同步設定方面遇到類似的問題嗎?任何建議將不勝感激!
以上是為什麼我的多執行緒 API 仍然很慢?的詳細內容。更多資訊請關注PHP中文網其他相關文章!