Azure Functions에서 Python 앱 메모리 사용량 프로파일링
개발 중에 또는 Azure에 로컬 Python 함수 앱 프로젝트를 배포한 후에는 함수의 잠재적 메모리 병목 상태에 대해 분석하는 것이 좋습니다. 이러한 병목 상태는 함수의 성능을 저하하고 오류를 일으킬 수 있습니다. 다음 지침에서는 메모리 프로파일러 Python 패키지를 사용하는 방법을 보여줍니다. 이 패키지는 함수 실행 시 함수에 대한 라인별 메모리 사용량 분석을 제공합니다.
참고 항목
메모리 프로파일링은 개발 환경의 메모리 공간을 분석하는 용도로만 사용됩니다. 메모리 프로파일러를 프로덕션 함수 앱에 적용하지 마세요.
필수 조건
Python 함수 앱 개발을 시작하기 전에 다음 요구 사항을 충족해야 합니다.
Python 3.7 이상. Azure Functions에서 지원되는 Python 버전의 전체 목록을 확인하려면 Python 개발자 가이드를 참조하세요.
Azure Functions Core Tools 버전 4.x 이상
func --version
을 사용하여 버전을 확인합니다. 업데이트에 대해 알아보려면 GitHub의 Azure Functions Core Tools를 참조하세요.지원되는 플랫폼 중 하나에 Visual Studio Code가 설치됩니다.
활성화된 Azure 구독.
Azure를 구독하고 있지 않다면 시작하기 전에 Azure 체험 계정을 만듭니다.
메모리 프로파일링 프로세스
requirements.txt에서
memory-profiler
를 추가하여 패키지가 배포와 함께 제공되도록 합니다. 로컬 머신에서 개발하는 경우 Python 가상 환경을 활성화하고pip install -r requirements.txt
에서 패키지를 확인할 수 있습니다.함수 스크립트(예: Python v1 프로그래밍 모델의 경우 __init__.py, v2 모델의 경우 function_app.py)에서
main()
함수 위에 다음 줄을 추가합니다. 이러한 줄은 루트 로거가 자식 로거 이름을 보고하도록 하므로 메모리 프로파일링 로그는 접두사memory_profiler_logs
로 구분할 수 있습니다.import logging import memory_profiler root_logger = logging.getLogger() root_logger.handlers[0].setFormatter(logging.Formatter("%(name)s: %(message)s")) profiler_logstream = memory_profiler.LogFile('memory_profiler_logs', True)
메모리 프로파일링이 필요한 함수 위에 다음 데코레이터를 적용합니다. 데코레이터는 트리거 진입점
main()
메서드에서 직접 작동하지 않습니다. 하위 함수를 만들고 데코레이트해야 합니다. 또한 메모리 프로파일러의 알려진 문제로 인해 비동기 코루틴에 적용할 때 코루틴 반환 값은 항상None
입니다.@memory_profiler.profile(stream=profiler_logstream)
Azure Functions Core Tools 명령
func host start
를 사용하여 로컬 컴퓨터에서 메모리 프로파일러를 테스트합니다. 함수를 호출할 때 메모리 사용량 보고서를 생성해야 합니다. 보고서에는 파일 이름, 코드 줄, 메모리 사용량, 메모리 증분 및 그 안에 있는 줄 내용이 포함됩니다.Azure의 기존 함수 앱 인스턴스에서 메모리 프로파일링 로그를 확인하려면 Application Insights, Logs에서 Kusto 쿼리를 사용하여 최근 호출에 대한 메모리 프로파일링 로그를 쿼리할 수 있습니다.
traces | where timestamp > ago(1d) | where message startswith_cs "memory_profiler_logs:" | parse message with "memory_profiler_logs: " LineNumber " " TotalMem_MiB " " IncreMem_MiB " " Occurrences " " Contents | union ( traces | where timestamp > ago(1d) | where message startswith_cs "memory_profiler_logs: Filename: " | parse message with "memory_profiler_logs: Filename: " FileName | project timestamp, FileName, itemId ) | project timestamp, LineNumber=iff(FileName != "", FileName, LineNumber), TotalMem_MiB, IncreMem_MiB, Occurrences, Contents, RequestId=itemId | order by timestamp asc
예시
다음은 각각 “HttpTriggerAsync” 및 “HttpTriggerSync”라는 비동기 및 동기 HTTP 트리거에서 메모리 프로파일링을 수행하는 예제입니다. Microsoft 홈페이지에 GET 요청을 간단하게 보내는 Python 함수 앱을 빌드합니다.
Python 함수 앱 만들기
Python 함수 앱은 지정된 Azure Functions 폴더 구조를 따라야 합니다. 프로젝트를 스캐폴드하려면 다음 명령을 실행하여 Azure Functions Core Tools를 사용하는 것이 좋습니다.
func init PythonMemoryProfilingDemo --python
cd PythonMemoryProfilingDemo
func new -l python -t HttpTrigger -n HttpTriggerAsync -a anonymous
func new -l python -t HttpTrigger -n HttpTriggerSync -a anonymous
파일 콘텐츠 업데이트
requirements.txt는 프로젝트에서 사용되는 패키지를 정의합니다. Azure Functions SDK 및 메모리 프로파일러 외에 aiohttp
비동기 HTTP 요청 및 requests
동기 HTTP 호출에 대해 소개합니다.
# requirements.txt
azure-functions
memory-profiler
aiohttp
requests
비동기 HTTP 트리거를 만듭니다.
비동기 HTTP 트리거 HttpTriggerAsync/__init__.py의 코드를 메모리 프로파일러, 루트 로거 형식 및 로거 스트리밍 바인딩을 구성하는 다음 코드로 바꿉니다.
# HttpTriggerAsync/__init__.py
import azure.functions as func
import aiohttp
import logging
import memory_profiler
# Update root logger's format to include the logger name. Ensure logs generated
# from memory profiler can be filtered by "memory_profiler_logs" prefix.
root_logger = logging.getLogger()
root_logger.handlers[0].setFormatter(logging.Formatter("%(name)s: %(message)s"))
profiler_logstream = memory_profiler.LogFile('memory_profiler_logs', True)
async def main(req: func.HttpRequest) -> func.HttpResponse:
await get_microsoft_page_async('https://microsoft.com')
return func.HttpResponse(
f"Microsoft page loaded.",
status_code=200
)
@memory_profiler.profile(stream=profiler_logstream)
async def get_microsoft_page_async(url: str):
async with aiohttp.ClientSession() as client:
async with client.get(url) as response:
await response.text()
# @memory_profiler.profile does not support return for coroutines.
# All returns become None in the parent functions.
# GitHub Issue: https://github.com/pythonprofilers/memory_profiler/issues/289
동기 HTTP 트리거를 만듭니다.
비동기 HTTP 트리거 HttpTriggerSync/__init__.py의 코드를 다음 코드로 바꿉니다.
# HttpTriggerSync/__init__.py
import azure.functions as func
import requests
import logging
import memory_profiler
# Update root logger's format to include the logger name. Ensure logs generated
# from memory profiler can be filtered by "memory_profiler_logs" prefix.
root_logger = logging.getLogger()
root_logger.handlers[0].setFormatter(logging.Formatter("%(name)s: %(message)s"))
profiler_logstream = memory_profiler.LogFile('memory_profiler_logs', True)
def main(req: func.HttpRequest) -> func.HttpResponse:
content = profile_get_request('https://microsoft.com')
return func.HttpResponse(
f"Microsoft page response size: {len(content)}",
status_code=200
)
@memory_profiler.profile(stream=profiler_logstream)
def profile_get_request(url: str):
response = requests.get(url)
return response.content
로컬 개발 환경에서 Python 함수 앱 프로파일링
위의 변경 사항을 수행한 후 Azure Functions 런타임에 대한 Python 가상 환경을 초기화하는 몇 가지 단계가 더 있습니다.
Windows PowerShell 또는 Linux 셸 중 하나를 엽니다.
py -m venv .venv
(Windows용) 또는python3 -m venv .venv
(Linux용)로 Python 가상 환경을 만듭니다..venv\Scripts\Activate.ps1
(Windows PowerShell용) 또는source .venv/bin/activate
(Linux 셸용)로 Python 가상 환경을 활성화합니다.pip install -r requirements.txt
를 통해 Python 종속성을 복원합니다.Azure Functions Core Tools
func host start
를 이용하여 Azure Functions 런타임을 로컬에서 시작합니다.https://localhost:7071/api/HttpTriggerAsync
또는https://localhost:7071/api/HttpTriggerSync
에 GET 요청을 보냅니다.Azure Functions Core Tools의 다음 섹션과 유사한 메모리 프로파일링 보고서가 표시되어야 합니다.
Filename: <ProjectRoot>\HttpTriggerAsync\__init__.py Line # Mem usage Increment Occurrences Line Contents ============================================================ 19 45.1 MiB 45.1 MiB 1 @memory_profiler.profile 20 async def get_microsoft_page_async(url: str): 21 45.1 MiB 0.0 MiB 1 async with aiohttp.ClientSession() as client: 22 46.6 MiB 1.5 MiB 10 async with client.get(url) as response: 23 47.6 MiB 1.0 MiB 4 await response.text()
다음 단계
Azure Functions Python 개발에 대한 자세한 내용은 다음 리소스를 참조하세요.