分享方式:


在 Azure Functions 中分析 Python 應用程式記憶體使用量

在開發期間或將本地 Python 函數應用程式專案部署到 Azure 之後,最好分析函數中潛在的記憶體瓶頸。 這類瓶頸可能會降低函數的效能,並導致錯誤。 下列指示示範如何使用記憶體分析工具 Python 套件,這會在函數執行時提供逐行記憶體使用量分析。

注意

記憶體分析僅適用於開發環境中的磁碟使用量分析。 請勿在生產函數應用程式上套用記憶體分析工具。

必要條件

開始開發 Python 函數應用程式之前,您必須符合下列需求:

如果您沒有 Azure 訂用帳戶,請在開始之前先建立 Azure 免費帳戶

記憶體分析程序

  1. 在 requirements.txt 中,新增 memory-profiler 以確保部署會隨附該套件。 如果您要在本機電腦上開發,可能會要啟用 Python 虛擬環境,並透過 pip install -r requirements.txt 執行套件解析。

  2. 在函數指令碼中 (例如 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)
    
  3. 在需要記憶體分析的任何函數上方套用下列裝飾項目。 該裝飾項目無法直接在觸發程序進入點 main() 方法上運作。 您必須建立子函數並加以裝飾。 此外,由於記憶體分析工具的已知問題,在套用至非同步協同程式時,協同程式傳回值一律為 None

    @memory_profiler.profile(stream=profiler_logstream)
    
  4. 使用 Azure Functions Core Tools 命令 func host start,在本機電腦上測試記憶體分析工具。 當您叫用函數時,它們應會產生記憶體使用量報告。 這報告包含檔案名、程式碼、記憶體使用量、記憶體增量,以及其中的行內容。

  5. 若要檢查 Azure 中現有函數應用程式執行個體上的記憶體分析記錄,您可以使用 Application Insights、Logs 中的 Kusto 查詢,以查詢最近叫用的記憶體分析記錄。

    Screenshot showing the query memory usage of a Python app in Application Insights.

    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 虛擬環境。

  1. 視需要開啟 Windows PowerShell 或任何 Linux 殼層。

  2. 在 Windows 透過 py -m venv .venv,或在 Linux 中透過 python3 -m venv .venv 建立 Python 虛擬環境。

  3. 在 Windows PowerShell 透過 .venv\Scripts\Activate.ps1,或在 Linux 殼層中透過 source .venv/bin/activate 啟用 Python 虛擬環境。

  4. 使用 pip install -r requirements.txt 還原 Python 相依性

  5. 使用 Azure Functions Core Tools func host start 在本地啟動 Azure Functions 執行階段

  6. 將 GET 要求傳送至 https://localhost:7071/api/HttpTriggerAsynchttps://localhost:7071/api/HttpTriggerSync

  7. 它應該會顯示類似以下 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 開發的詳細資訊,請參閱下列資源: