在 Azure Functions 中分析 Python 應用程式記憶體使用量
在開發期間或將本地 Python 函數應用程式專案部署到 Azure 之後,最好分析函數中潛在的記憶體瓶頸。 這類瓶頸可能會降低函數的效能,並導致錯誤。 下列指示示範如何使用記憶體分析工具 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
範例
以下是在非同步和同步 HTTP 觸發程序上 (分別名為「HttpTriggerAsync」和「HttpTriggerSync」) 執行記憶體分析的範例。 我們會建置只會將 GET 要求傳送至 Microsoft 首頁的 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 殼層。
在 Windows 透過
py -m venv .venv
,或在 Linux 中透過python3 -m venv .venv
建立 Python 虛擬環境。在 Windows PowerShell 透過
.venv\Scripts\Activate.ps1
,或在 Linux 殼層中透過source .venv/bin/activate
啟用 Python 虛擬環境。使用
pip install -r requirements.txt
還原 Python 相依性使用 Azure Functions Core Tools
func host start
在本地啟動 Azure Functions 執行階段將 GET 要求傳送至
https://localhost:7071/api/HttpTriggerAsync
或https://localhost:7071/api/HttpTriggerSync
。它應該會顯示類似以下 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 開發的詳細資訊,請參閱下列資源: