>백엔드 개발 >파이썬 튜토리얼 >내 멀티스레드 API가 여전히 느린 이유는 무엇입니까?

내 멀티스레드 API가 여전히 느린 이유는 무엇입니까?

DDD
DDD원래의
2024-12-07 20:49:17798검색

Why is My Multi-Threaded API Still Slow?

API에 문제가 있습니다. 누군가 도움을 줄 수 있기를 바랍니다. 멀티스레딩을 추가했음에도 불구하고 성능 향상은 기대했던 것과는 거리가 멀었습니다. 이상적으로는 하나의 스레드가 작업을 완료하는 데 1초가 걸리면 동시에 실행되는 10개의 스레드도 약 1초가 걸립니다(제가 이해한 바입니다). 하지만 내 API 응답 시간은 여전히 ​​매우 느립니다.

문제

저는 Playwright, MongoDB, ThreadPoolExecutor 같은 라이브러리와 함께 FastAPI를 사용하고 있습니다. 목표는 CPU 바인딩 작업에는 스레딩을 사용하고 IO 바인딩 작업에는 async-await를 사용하는 것이었습니다. 그래도 응답 시간이 예상만큼 개선되지 않습니다.

도서 자동화 예시

내 프로젝트의 한 부분은 EPUB 뷰어와 상호작용하기 위해 Playwright를 사용하여 도서 검색을 자동화하는 것입니다. 다음 기능은 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.0028초입니다

리팩터링 예

GIL을 피하고 워크로드를 적절하게 관리하기 위해 run_in_executor()를 사용하여 ProcessPoolExecutor에서 함수를 실행했습니다.

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.