AWS LambdaにおけるARM64とx86_64の性能比較


## はじめに

AWS Lambdaは、ARM64（Graviton2）とx86_64の2種類のアーキテクチャで動作します。ARM64はモバイル向けや低消費電力が特徴のRISCアーキテクチャで、一方x86_64はサーバー向けに広く使われるCISCアーキテクチャです。

今回は、AWS Lambdaで**ARM64**と**x86_64**のパフォーマンスを、I/Oバウンド処理、CPUバウンド処理、並列処理の観点で比較しました。Pythonを用いたサンプルコードを実行し、メモリサイズごとの処理時間を測定しました。

## サンプルコード

次のPythonコードをAWS LambdaでARM64とx86_64の両方で実行しました。このコードは以下の3種類の処理を行います。

1. **I/Oバウンド処理**: ファイルの読み書きでI/O性能を測定。
2. **CPUバウンド処理**: 浮動小数点演算を大量に行うことでCPUの性能を測定。
3. **並列処理**: スレッドを用いた並列計算のパフォーマンスを測定。

```python
import time
import math
import threading

def io_bound_computation():
    start_time = time.time()
    
    # ファイルの読み書きでI/Oバウンド処理をシミュレート
    filename = "/tmp/test_file.txt"
    with open(filename, "w") as f:
        for i in range(10**6):
            f.write(f"{i}\n")
    
    with open(filename, "r") as f:
        lines = f.readlines()

    end_time = time.time()
    return end_time - start_time

def cpu_bound_computation():
    start_time = time.time()
    
    # 浮動小数点演算によるCPUバウンド処理
    result = 0
    for i in range(1, 10**6):
        result += math.sqrt(i) * math.sin(i)
    
    end_time = time.time()
    return end_time - start_time

def parallel_computation():
    start_time = time.time()
    
    # 並列処理をシミュレート
    def worker(result_list, index):
        result = 0
        for i in range(index * 10**5, (index + 1) * 10**5):
            result += i
        result_list[index] = result

    num_threads = 4
    threads = []
    results = [0] * num_threads

    for i in range(num_threads):
        thread = threading.Thread(target=worker, args=(results, i))
        threads.append(thread)
        thread.start()

    for thread in threads:
        thread.join()

    return time.time() - start_time

def lambda_handler(event, context):
    # 各処理の時間を測定
    io_time = io_bound_computation()
    cpu_time = cpu_bound_computation()
    parallel_time = parallel_computation()

    return {
        'io_bound_time': io_time,
        'cpu_bound_time': cpu_time,
        'parallel_time': parallel_time
    }
```

## 実験環境と前提条件

- **AWS Lambda**の実行環境で、ARM64とx86_64の両方で同じコードを実行しました。
- メモリサイズを128MB、256MB、512MB、1024MBに設定してパフォーマンスを測定しました。
- 各処理にかかった実行時間を比較しています。

## 結果

下表は、ARM64とx86_64における各処理の実行時間を示しています。I/Oバウンド処理、CPUバウンド処理、並列処理のいずれにおいても、ARM64がx86_64よりも優れた結果を示しました。

| Memory (MB) | ARM64 IO Bound Time (s) | x86_64 IO Bound Time (s) | ARM64 CPU Bound Time (s) | x86_64 CPU Bound Time (s) | ARM64 Parallel Time (s) | x86_64 Parallel Time (s) |
|-------------|--------------------------|--------------------------|--------------------------|--------------------------|-------------------------|-------------------------|
| 128         | 3.999                    | 5.517                    | 2.493                    | 4.057                    | 0.278                   | 0.362                   |
| 256         | 1.973                    | 2.668                    | 1.185                    | 1.880                    | 0.173                   | 0.196                   |
| 512         | 0.997                    | 1.318                    | 0.580                    | 0.935                    | 0.112                   | 0.099                   |
| 1024        | 0.479                    | 0.675                    | 0.294                    | 0.485                    | 0.056                   | 0.053                   |

## 考察

- **I/Oバウンド処理**では、メモリサイズが大きくなるにつれて両アーキテクチャで実行時間が短縮されますが、ARM64の方が全体的にパフォーマンスが良い結果となりました。
- **CPUバウンド処理**では、浮動小数点演算が多いため、ARM64がより効率的な処理を行っていることが伺えます。
- **並列処理**についても、ARM64がわずかに優れた結果を示しましたが、メモリサイズが増大するにつれx86_64との差は小さくなっています。

## 結論

この結果から、ARM64アーキテクチャ（AWS Graviton2）は、低消費電力でありながら、I/Oや計算負荷が高い処理においても優れたパフォーマンスを発揮することが確認されました。特に、AWS Lambda環境においてコスト効率の良い選択肢となる可能性があります。

## 最後に
Graviton2は最大34%優れた料金パフォーマンスがある！というのだけ知っていて「どうせ低消費電力化したからその分安くするけど、実行効率は原則少し落ちるからトントンくらい」ということだと思っていたのでこの結果には驚きました。もちろん複雑な処理が全てそうだとは言えないと思いますがこの結果だと数値以上の恩恵を受けられるんじゃないかと思います。
今度はarmでは動かない処理などで検証してみたくなりました。


---