

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 透過 Lambda 執行程式碼
<a name="concepts-how-lambda-runs-code"></a>

當您編寫 Lambda 函式時，其實是在建立將在獨特的無伺服器環境中執行的程式碼。了解 Lambda 實際執行程式碼的運作原理，需掌握兩個核心面向：定義程式碼與 Lambda 互動方式的程式設計模型，以及決定 Lambda 如何管理程式碼執行時期環境的執行環境生命週期。

## Lambda 程式設計模型
<a name="concepts-progmodel-overview"></a>

無論您是以 Python、Java 或任何其他支援的語言撰寫，程式設計模型都會做為 Lambda 如何使用程式碼的常見規則集。程式設計模型包含您的執行時期與處理常式。

**對於標準函數：**

1. Lambda 收到事件。

1. Lambda 會使用執行時間，以您的程式碼可以使用的格式準備事件。

1. 執行時期將格式化的事件傳送至您的處理常式。

1. 您的處理常式會使用您撰寫的程式碼來處理事件。

**對於耐用函數：**

1. Lambda 收到事件

1. 執行時間會準備事件和 DurableContext

1. 您的處理常式可以：
   + 使用自動檢查點處理步驟
   + 暫停執行而不耗用資源
   + 從最後一個成功的檢查點繼續
   + 在步驟之間維持狀態

此模型的關鍵是*處理常式*，這是 Lambda 將事件傳送給您的程式碼進行處理的入口。您可以將其視為程式碼的進入點。當 Lambda 收到事件時，會將此事件與部分內容資訊傳遞給您的處理常式。然後，處理常式會執行您的程式碼來處理這些事件。例如，其可能會在有檔案上傳至 Amazon S3 時讀取該檔案、分析映像或更新資料庫。當程式碼完成事件處理後，處理常式即準備就緒，可繼續處理下一個事件。

## Lambda 執行模型
<a name="concepts-exec-env-overview"></a>

雖然程式設計模型會定義 Lambda 與您的程式碼互動的方式，但執行環境是 Lambda 實際執行函數的位置，這是專為您的函數建立的安全隔離運算空間。

**每個環境遵循的生命週期會因標準和耐用函數而異：**

**標準函數 （最多 15 分鐘）：**

1. **初始化：**環境設定和程式碼載入

1. **調用：**函數程式碼的單一執行

1. **關閉：**環境清除

**耐用函數 （最長 1 年）：**

1. **初始化：**環境和持久狀態設定

1. **調用：**具有自動檢查點的多個步驟

1. **等待狀態：**暫停執行而不耗用資源

1. **繼續：**從最後一個檢查點重新啟動

1. **關閉：**清除持久狀態

此環境會處理執行函式所涉及的重要層面。其會為函式提供記憶體與 `/tmp` 目錄用於暫時儲存。**對於持久性函數，它也會管理：**
+ 步驟之間的自動狀態持久性
+ 檢查點儲存和復原
+ 等待狀態協調
+ 長時間執行執行的進度追蹤

# 了解 Lambda 程式設計模型
<a name="foundation-progmodel"></a>

Lambda 提供兩種程式設計模型：執行最多 15 分鐘的標準函數，以及執行最多一年的耐久函數。雖然兩者都共用核心概念，但耐用函數為長時間執行且具狀態的工作流程新增了功能。

Lambda 提供的程式設計模型對於所有執行時間通用。程式設計模型會定義程式碼與 Lambda 系統之間的介面。透過在函數組態中定義一個*處理常式*，將函數的進入點告知 Lambda。執行時間會將包含呼叫*事件*和*內容*的物件傳入至處理常式，例如函數名稱和請求 ID。

**對於耐用函數，處理常式也會收到 DurableContext 物件，提供：**
+ 透過 step() 的檢查點功能
+ 透過 wait() 和 waitForCallback() 等待狀態管理
+ 叫用之間的自動狀態持續性

當處理常式完成處理第一個事件時，執行時間就會傳送至另一個。對於耐用函數，處理常式可以暫停步驟之間的執行，而且 Lambda 將在函數恢復時自動儲存和還原狀態。函數的類別會保留在記憶體中，因此可以重複使用在*初始化程式碼*的處理常式方法外宣告的用戶端和變數。為了節省後續事件的處理時間，請建立可重複使用的資源，例如初始化期間的 AWS SDK 用戶端。初始化後，函式的每個執行個體都可以處理數千個請求。

您的函數也可以存取 `/tmp` 目錄中的本機儲存體，此暫時性快取可用於多個調用。如需詳細資訊，請參閱[執行環境](lambda-runtime-environment.md)。

啟用[AWS X-Ray 追蹤](services-xray.md)時，執行時間會記錄初始化和執行的個別子區段。

執行時間會從您的函數擷取記錄輸出，並將其傳送至 Amazon CloudWatch Logs。除了記錄函式的輸出之外，執行階段也會記錄函式叫用開始和結束的項目。這包含有要求 ID、帳單期、初始化持續時間和其他詳細資料的記錄。如果函數拋出錯誤，執行時間會將該錯誤傳回給叫用者。

**注意**  
記錄受 [CloudWatch Logs 配額](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/cloudwatch_limits_cwl.html)限制。日誌資料可能會因節流而遺失，或在某些情況下，因函數的執行個體停止而遺失。

**持久性函數的主要差異：**
+ 狀態會在步驟之間自動保留
+ 函數可以暫停執行而不耗用資源
+ 步驟會在失敗時自動重試
+ 透過檢查點追蹤進度

Lambda 會隨著需求增加執行額外的執行個體，以及隨需求降低停止執行個體，藉以擴展您的函數。此模型會導致應用程式結構的變化，例如：
+ 除非另有說明，否則可能會不按順序或同時處理傳入的請求。
+ 不依賴函數長期存留的執行個體，而是將應用程式的狀態存放在其他服務中。
+ 使用本機儲存和類別層級物件來提高效能，但將部署套裝服務的大小和傳輸至執行環境的資料量降至最低。

如需使用慣用程式設計語言的程式設計模型實作簡介，請參閱以下章節。
+ [使用 Node.js 建置 Lambda 函數](lambda-nodejs.md)
+ [使用 Python 建置 Lambda 函數](lambda-python.md)
+ [使用 Ruby 建置 Lambda 函數](lambda-ruby.md)
+ [使用 Java 建置 Lambda 函數](lambda-java.md)
+ [使用 Go 建置 Lambda 函數](lambda-golang.md)
+ [使用 C\$1 建置 Lambda 函數](lambda-csharp.md)
+ [使用 PowerShell 建置 Lambda 函數](lambda-powershell.md)

# 了解 Lambda 執行環境生命週期
<a name="lambda-runtime-environment"></a>

Lambda 執行環境支援標準函數 （最多 15 分鐘） 和耐用函數 （最多一年）。雖然兩者共用相同的基本生命週期，但耐用函數會為長時間執行的工作流程新增狀態管理功能。

 Lambda 會在執行環境中叫用您的函數，該環境可提供安全且隔離的執行時間環境。執行環境會管理執行函式所需的資源。執行環境也會提供函式執行階段的生命週期支援，以及與函式相關聯的任何[外部延伸項目](lambda-extensions.md)。

**對於耐用函數，執行環境包含以下項目的其他元件：**
+ 步驟之間的狀態持久性
+ 檢查點管理
+ 等待狀態協調
+ 進度追蹤

**Lambda 受管執行個體執行環境**  
如果您使用的是 [Lambda 受管執行個體](lambda-managed-instances-execution-environment.md)，執行環境與 Lambda （預設） 函數有重要的差異。受管執行個體支援並行調用、使用不同的生命週期模型，以及在客戶擁有的基礎設施上執行。如需受管執行個體執行環境的詳細資訊，請參閱 [了解 Lambda 受管執行個體執行環境](lambda-managed-instances-execution-environment.md)。

函數的執行時間會使用 [Runtime API](runtimes-api.md) 與 Lambda 進行通訊。延伸項目會使用 [Extensions API](runtimes-extensions-api.md) 與 Lambda 進行通訊。延伸項目還可以透過使用[遙測 API](telemetry-api.md) 來接收函數的日誌訊息和其他遙測項目。



![\[執行環境的架構圖表。\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/telemetry-api-concept-diagram.png)


當您建立 Lambda 函數時，您將指定組態資訊，例如您的函數允許的記憶體數量與執行時間上限。Lambda 會使用此資訊來設定執行環境。

函式的執行階段和每個外部延伸項目都是在執行環境中執行的程序。許可、資源、認證和環境變數會在函式和延伸項目之間共用。

**Topics**
+ [

## Lambda 執行環境生命週期
](#runtimes-lifecycle)
+ [

## 冷啟動和延遲
](#cold-start-latency)
+ [

## 使用佈建並行減少冷啟動
](#cold-starts-pc)
+ [

## 最佳化靜態初始化
](#static-initialization)

## Lambda 執行環境生命週期
<a name="runtimes-lifecycle"></a>

![\[Lambda 生命週期階段：初始化、調用、關閉\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/Overview-Successful-Invokes.png)


每個階段都以 Lambda 傳送到執行階段和所有已註冊延伸項目的事件開始。執行時間和每個已註冊延伸項目都會透過傳送 `Next` API 請求來表示已完成。當執行時間和每個延伸項目已完成且沒有擱置的事件時，Lambda 凍結執行環境。

**耐用函數的生命週期階段包括：**
+ **初始化：**標準初始化加上持久狀態設定
+ **調用：**可以包含具有自動檢查點的多個步驟執行
+ **等待：**函數可以暫停執行，而不會耗用資源
+ **繼續：**從最後一個檢查點重新啟動函數
+ **關閉：**清除耐用狀態和資源

**Topics**
+ [

### 初始化階段
](#runtimes-lifecycle-ib)
+ [

### 初始化階段期間出現的失敗
](#runtimes-lifecycle-init-errors)
+ [

### 還原階段 (僅限 Lambda SnapStart)
](#runtimes-lifecycle-restore)
+ [

### 調用階段
](#runtimes-lifecycle-invoke)
+ [

### 調用階段期間出現的故障
](#runtimes-lifecycle-invoke-with-errors)
+ [

### 關閉階段
](#runtimes-lifecycle-shutdown)

### 初始化階段
<a name="runtimes-lifecycle-ib"></a>

在 `Init` 階段中，Lambda 會執行三項任務：
+ 啟動所有延伸項目 (`Extension init`)
+ Bootstrap 執行時間 (`Runtime init`)
+ 執行該函式的靜態代碼 (`Function init`)
+ 執行任何檢查點前的[執行時期勾點](snapstart-runtime-hooks.md) (僅限 Lambda SnapStart)

當執行階段和所有延伸項目透過傳送 `Next` API 請求發出訊號表示它們已準備就緒時，`Init` 階段便會結束。`Init` 階段限制為 10 秒。如果所有三項任務都未在 10 秒內完成，Lambda 會在第一次函數調用時以設定的函數逾時重試 `Init` 階段。

在 [Lambda SnapStart](snapstart.md) 啟動的情況下，發佈函數版本時會發生 `Init` 階段。Lambda 會儲存初始化執行環境的記憶體和磁碟狀態快照、保留加密的快照，並快取以進行低延遲存取。如果您擁有檢查點前的[執行時期勾點](snapstart-runtime-hooks.md)，則程式碼會在 `Init` 階段結束時執行。

**注意**  
10 秒逾時不適用於使用佈建並行、SnapStart 或 Lambda 受管執行個體的函數。對於佈建並行、SnapStart 和受管執行個體函數，初始化程式碼最多可執行 15 分鐘。時間限制為 130 秒或設定的函數逾時 (最長 900 秒)，以較長者為準。

使用[佈建並行](https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html)時，當您設定函數的電腦設定，Lambda 會初始化執行環境。Lambda 也可確保初始化的執行環境在調用之前隨時可用。您會發現函數調用和初始化階段之間出現差距。根據函數的執行期和記憶體組態，您也會在初始化的執行環境上第一次調用時看到變數延遲。

對於使用隨需並行的函數，Lambda 偶爾會在調用請求之前初始化執行環境。發生這種情況時，您也會注意到函數初始化和調用階段之間出現時間差。建議您不要依賴此行為。

### 初始化階段期間出現的失敗
<a name="runtimes-lifecycle-init-errors"></a>

如果在 `Init` 階段期間函數當機或出現逾時，Lambda 會在 `INIT_REPORT` 日誌檔中發出錯誤資訊。

**Example — 逾時的 INIT\$1REPORT 日誌**  

```
INIT_REPORT Init Duration: 1236.04 ms Phase: init Status: timeout
```

**Example — 延伸失敗的 INIT\$1REPORT 日誌**  

```
INIT_REPORT Init Duration: 1236.04 ms Phase: init Status: error Error Type: Extension.Crash
```

如果 `Init` 階段成功，除非已啟用 [SnapStart](snapstart.md) 或[佈建並行](provisioned-concurrency.md)，否則 Lambda 不會發出 `INIT_REPORT` 日誌。SnapStart 和佈建並行函數一律會發出 `INIT_REPORT`。如需詳細資訊，請參閱[監控 Lambda SnapStart](snapstart-monitoring.md)。

### 還原階段 (僅限 Lambda SnapStart)
<a name="runtimes-lifecycle-restore"></a>

第一次調用 [SnapStart](snapstart.md) 函數且函數擴展時，Lambda 會從保留的快照繼續新的執行環境，而不是從頭開始初始化函數。如果您設定了還原後[執行時期勾點](snapstart-runtime-hooks.md)，其程式碼會在 `Restore` 階段結束時執行。您需支付還原後執行時期勾點期間的費用。執行時期必須完成載入，且還原後執行時期勾點必須在逾時限制 (10 秒) 內完成。否則，您將收到 SnapStartTimeoutException 訊息。`Restore` 階段完成時，Lambda 會調用函數處理常式 ([調用階段](#runtimes-lifecycle-invoke))。

#### 還原階段期間出現的失敗
<a name="runtimes-lifecycle-restore-errors"></a>

如果 `Restore` 階段失敗，Lambda 會在 `RESTORE_REPORT` 日誌檔中發出錯誤資訊。

**Example — 逾時的 RESTORE\$1REPORT 日誌**  

```
RESTORE_REPORT Restore Duration: 1236.04 ms Status: timeout
```

**Example — 執行期勾點失敗的 RESTORE\$1REPORT 日誌**  

```
RESTORE_REPORT Restore Duration: 1236.04 ms Status: error Error Type: Runtime.ExitError
```

如需`RESTORE_REPORT` 日誌的詳細資訊，請參閱 [監控 Lambda SnapStart](snapstart-monitoring.md)。

### 調用階段
<a name="runtimes-lifecycle-invoke"></a>

調用 Lambda 函數以回應 `Next` API 請求時，Lambda 會將 `Invoke` 事件傳送至執行時間和每個延伸項目。

該函式的逾時設定會限制整個 `Invoke` 階段的持續時間。例如，如果您將函式逾時設定為 360 秒，則函式和所有延伸項目都需要在 360 秒內完成。請注意，沒有獨立的調用後階段。持續時間是所有調用時間 (執行階段 \$1 延伸項目) 的總和，直到函式和所有延伸項目完成執行後才會計算。

調用階段會在執行階段後結束，所有延伸項目訊號都透過傳送 `Next` API 請求完成。

### 調用階段期間出現的故障
<a name="runtimes-lifecycle-invoke-with-errors"></a>

如果 Lambda 函數當機或在 `Invoke` 階段逾時，Lambda 會重設執行環境。下圖會說明發生調用故障時 Lambda 執行環境的行為：

![\[執行環境範例：初始化、調用、調用出現錯誤、調用、關閉\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/Overview-Invoke-with-Error.png)


在前一張示意圖中：
+ 第一階段是 **INIT** 階段，執行期間未發生錯誤。
+ 第二階段是 **INVOKE** 階段，執行期間未發生錯誤。
+ 假設在某個時間點，函式遇到調用失敗 (常見原因包括函式逾時、執行時期錯誤、記憶體耗盡、VPC 連線問題、許可錯誤、並行限制以及各種組態問題)。如需可能調用失敗的完整清單，請參閱[針對 Lambda 中的調用問題進行疑難排解](troubleshooting-invocation.md)。第三階段 (標記為「**INVOKE WITH ERROR**」) 會說明此狀況。發生此狀況時，Lambda 服務會進行重設。重設的行為會與 `Shutdown` 事件一樣。首先，Lambda 會關閉執行階段，然後將 `Shutdown` 事件傳送給每個已註冊的外部延伸項目。事件會包括關閉的原因。如果將此環境用於新的調用，Lambda 便會在下一次調用時重新初始化延伸項目和執行階段。

  請注意，在下一個初始化階段之前，Lambda 重設不會清除 `/tmp` 目錄內容。這種行為與一般關機階段一致。
**注意**  
AWS 目前正在對 Lambda 服務實作變更。由於這些變更，您可能會看到系統日誌訊息的結構和內容，與 AWS 帳戶中不同 Lambda 函數發出的追蹤區段之間存在細微差異。  
如果函數的系統日誌組態設為純文字，則此變更會影響函數發生調用失敗時在 CloudWatch Logs 中擷取的日誌訊息。下列範例展示了舊格式和新格式的日誌輸出。  
這些變化將在未來幾週內實作，除中國和 GovCloud 區域以外，所有 AWS 區域 中的所有函數都會轉換至使用新格式的日誌訊息和追蹤區段。

    
**Example CloudWatch Logs 日誌輸出 (執行時期或延伸項目損毀) - 舊式**  

  ```
  START RequestId: c3252230-c73d-49f6-8844-968c01d1e2e1 Version: $LATEST
  RequestId: c3252230-c73d-49f6-8844-968c01d1e2e1 Error: Runtime exited without providing a reason
  Runtime.ExitError
  END RequestId: c3252230-c73d-49f6-8844-968c01d1e2e1
  REPORT RequestId: c3252230-c73d-49f6-8844-968c01d1e2e1 Duration: 933.59 ms Billed Duration: 934 ms Memory Size: 128 MB Max Memory Used: 9 MB
  ```  
**Example CloudWatch Logs 日誌輸出 (函數逾時) - 舊式**  

  ```
  START RequestId: b70435cc-261c-4438-b9b6-efe4c8f04b21 Version: $LATEST
  2024-03-04T17:22:38.033Z b70435cc-261c-4438-b9b6-efe4c8f04b21 Task timed out after 3.00 seconds
  END RequestId: b70435cc-261c-4438-b9b6-efe4c8f04b21
  REPORT RequestId: b70435cc-261c-4438-b9b6-efe4c8f04b21 Duration: 3004.92 ms Billed Duration: 3117 ms Memory Size: 128 MB Max Memory Used: 33 MB Init Duration: 111.23 ms
  ```

  CloudWatch Logs 的新格式包括 `REPORT` 行中的額外 `status` 欄位。在執行時期或延伸項目損毀的情況下，該 `REPORT` 行也包含欄位 `ErrorType`。

    
**Example CloudWatch Logs 日誌輸出 (執行時期或延伸項目損毀) - 新式**  

  ```
  START RequestId: 5b866fb1-7154-4af6-8078-6ef6ca4c2ddd Version: $LATEST
  END RequestId: 5b866fb1-7154-4af6-8078-6ef6ca4c2ddd
  REPORT RequestId: 5b866fb1-7154-4af6-8078-6ef6ca4c2ddd Duration: 133.61 ms Billed Duration: 214 ms Memory Size: 128 MB Max Memory Used: 31 MB Init Duration: 80.00 ms Status: error Error Type: Runtime.ExitError
  ```  
**Example CloudWatch Logs 日誌輸出 (函數逾時) - 新式**  

  ```
  START RequestId: 527cb862-4f5e-49a9-9ae4-a7edc90f0fda Version: $LATEST
  END RequestId: 527cb862-4f5e-49a9-9ae4-a7edc90f0fda
  REPORT RequestId: 527cb862-4f5e-49a9-9ae4-a7edc90f0fda Duration: 3016.78 ms Billed Duration: 3101 ms Memory Size: 128 MB Max Memory Used: 31 MB Init Duration: 84.00 ms Status: timeout
  ```
+ 第四階段指的是出現調用故障後立即進入的 **INVOKE** 階段。在此階段中，Lambda 會透過重新執行 **INIT** 階段來再次初始化環境。(我們將其稱為*隱藏的初始化*。) 發生隱藏的初始化時，Lambda 不會在 CloudWatch Logs 中明確回報其他 **INIT** 階段。相反地，您可能會注意到 REPORT 行中的持續時間包含其他的 **INIT** 持續時間以及 **INVOKE** 持續時間。舉例來說，假設您在 CloudWatch 中看到以下日誌：

  ```
  2022-12-20T01:00:00.000-08:00 START RequestId: XXX Version: $LATEST 
  2022-12-20T01:00:02.500-08:00 END RequestId: XXX 
  2022-12-20T01:00:02.500-08:00 REPORT RequestId: XXX Duration: 3022.91 ms 
  Billed Duration: 3000 ms Memory Size: 512 MB Max Memory Used: 157 MB
  ```

  在這個例子中，REPORT 和 START 時間戳記之間的差距是 2.5 秒。這與回報的 3022.91 毫秒持續時間不相符，因為它不會將 Lambda 執行的額外 **INIT**（隱藏的初始化） 納入考量。在這個例子中，您可以推斷實際的 **INVOKE** 階段花費了 2.5 秒的時間。

  若要深入了解此行為，您可以使用 [使用遙測 API 即時存取延伸功能的遙測資料](telemetry-api.md). 調用階段發生隱藏的初始化時，遙測 API 便會透過 `phase=invoke` 發送 `INIT_START`、`INIT_RUNTIME_DONE` 及 `INIT_REPORT` 事件。
+ 第五階段指的是 **SHUTDOWN** 階段，執行期間未發生錯誤。

### 關閉階段
<a name="runtimes-lifecycle-shutdown"></a>

當 Lambda 即將關閉執行時間，它會將 `Shutdown` 事件傳送至每個已註冊外部延伸。延伸項目可以使用此時間進行最終清理工作。`Shutdown` 事件是對 `Next` API 請求的回應。

**持續時間限制**：`Shutdown` 階段的最長持續時間視已註冊延伸項目的組態而定：
+ 0 毫秒 - 沒有註冊延伸的函數
+ 500 毫秒 - 具有已註冊內部延伸項目的函數
+ 2,000 毫秒 - 具有一個或多個已註冊外部延伸項目的函數

如果執行時間或延伸項目未在限制內回應 `Shutdown` 事件，Lambda 會使用 `SIGKILL` 訊號結束程序。

在函數和所有延伸項目完成之後，Lambda 會維護執行環境一段時間，並預期另一個函數調用。不過，Lambda 每隔幾小時終止一次執行環境，以允許執行時期更新和維護，即使對於持續調用的函數也是如此。您不應該假設執行環境將無限期持續運作。如需詳細資訊，請參閱[在函式中實作無狀態](concepts-application-design.md#statelessness-functions)。

再次叫用函數時，Lambda 會解凍環境以重複使用。重複使用執行環境具有下列含義：
+ 在函數處理常式方法外宣告的物件會保持初始化，於再次呼叫函數時提供額外的最佳化。例如，假設您的 Lambda 函數建立資料庫連線，而不是重建連線，那麼在後續呼叫時便會使用原始連線。建議您在程式碼中新增邏輯，在建立連線前先確認是否存在既有連線。
+ 每個執行環境都會在 `/tmp` 目錄中提供 512 MB 到 10,240 MB 的磁碟空間，增量為 1 MB。執行內容凍結時，目錄環境會凍結，所提供的暫時性可用於多重調用。您可以新增額外的程式碼，確認快取是否具有您已儲存的資料。如需部署大小限制的詳細資訊，請參閱[Lambda 配額Lambda 配額](gettingstarted-limits.md)。
+ 如果 Lambda 重複使用執行環境，則會恢復由 Lambda 函數啟動且在函數結束時沒有完成的背景程序或回呼。請確定程式碼中的任何背景程序或回呼在程式碼存在前已完成。

## 冷啟動和延遲
<a name="cold-start-latency"></a>

當 Lambda 收到透過 Lambda API 執行函式的請求時，此服務會先準備執行環境。在此初始化階段，服務會下載程式碼、啟動環境，並執行主要處理常式外部的任何初始化程式碼。最後，Lambda 才會執行處理常式程式碼。

![\[效能最佳化圖 1\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/perf-optimize-figure-1.png)


在此圖表中，下載程式碼和設定環境的前兩個步驟通常稱為「冷啟動」。[這段時間會產生費用](https://aws.amazon.com/blogs/compute/aws-lambda-standardizes-billing-for-init-phase/)，且會增加調用的整體延遲時間。

調用完成之後，執行環境會凍結。為了改善資源管理和效能，Lambda 會將執行環境保留一段時間。在此期間，如果收到另一個針對相同函式的請求，Lambda 可以重複使用該環境。第二個請求通常會更快完成，因為執行環境已完全設定。這就是所謂的「暖啟動」。

冷啟動通常發生在不到 1% 的調用中。冷啟動的持續時間從低於 100 毫秒至超過 1 秒不等。一般而言，冷啟動在開發和測試函式中通常比在生產工作負載更為常見。這是因為開發和測試函數的調用頻率通常較低。

## 使用佈建並行減少冷啟動
<a name="cold-starts-pc"></a>

如果工作負載需要可預測的函式啟動時間，建議使用[佈建並行](provisioned-concurrency.md)解決方案，確保盡可能降低延遲。此功能會預先初始化執行環境，從而減少冷啟動時間。

例如，若函式的佈建並行為 6，表示具有 6 個預先暖啟動的執行環境。

![\[效能最佳化圖 4\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/perf-optimize-figure-4.png)


## 最佳化靜態初始化
<a name="static-initialization"></a>

靜態初始化在處理常式程式碼開始在函數中執行之前進行。這是您在主要處理常式外部提供的初始化程式碼。此程式碼通常用於匯入程式庫和相依項、設定組態，以及初始化與其他服務的連線。

下列 Python 範例示範了如何在調用期間執行 `lambda_handler` 函式之前，在初始化階段匯入和設定模組以及建立 Amazon S3 用戶端。

```
import os
import json
import cv2
import logging
import boto3

s3 = boto3.client('s3')
logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):

  # Handler logic...
```

函式執行前的延遲，主要來自初始化程式碼的執行時間。首次建立新的執行環境，即會執行此程式碼。如果調用使用暖執行環境，則不會再次執行初始化程式碼。影響初始化程式碼延遲的因素包括：
+ 函數套件的大小，包括匯入的程式庫和相依項以及 Lambda 層。
+ 程式碼和初始化工作的數量。
+ 程式庫和其他服務在設定連線及其他資源方面的表現。

開發人員可以採取多個步驟來最佳化靜態初始化延遲。如果一個函數具有許多物件和連線，您可以將單一函數重新架構為多個專用函數。這些函式各自較小，並且每個函式的初始化程式碼也更少。

重要的是，函數僅匯入所需的程式庫和相依項。例如，如果您只在 AWS SDK 中使用 Amazon DynamoDB，您可以要求個別服務，而不是整個 SDK。比較下列三個範例：

```
// Instead of const AWS = require('aws-sdk'), use:
const DynamoDB = require('aws-sdk/clients/dynamodb')

// Instead of const AWSXRay = require('aws-xray-sdk'), use:
const AWSXRay = require('aws-xray-sdk-core')

// Instead of const AWS = AWSXRay.captureAWS(require('aws-sdk')), use:
const dynamodb = new DynamoDB.DocumentClient()
AWSXRay.captureAWSClient(dynamodb.service)
```

靜態初始化通常也是開啟資料庫連線的最佳位置，可允許函式在對同一執行環境的多次調用中重複使用連線。但是，您可能具有大量僅在函數的某些執行路徑中使用的物件。在這種情況下，您可以在全域範圍內延遲載入變數，以縮短靜態初始化持續時間。

避免使用全域變數來取得特定內容的資訊。如果您的函數具有僅在單次調用的生命週期內使用並在下次調用時重設的全域變數，請使用處理常式本機的變數範圍。這不僅可以防止調用間的全域變數洩漏，還可以改善靜態初始化效能。