✈️

AWS Lambda x86_64とarm64で処理速度どれだけ違うか調べてみた

2021/12/24に公開

この記事は、AWS LambdaとServerless Advent Calendar 2021 23日目の記事です。
遅れてしまってすみません。

きっかけ

以前から作りたいものがあって、途中まで作ってたりはしていたんですが、そろそろ本腰入れて作るかなと思って、どんな設計にするかと考えています。

作りたいもの自体は、
趣味で、飛行機写真を撮っていて、関東在住なので、羽田空港や成田空港に行くんですが、そんな時に気になるのが天気。
まあ、東京なり千葉の天気で大体はわかるのですが、空港には、パイロットなどの航空関係者向けに、定時飛行場実況気象通報式(METAR) というものがあって、結構リアルタイム(変化がなければ15分おきぐらいに更新)にわかるものです。(超絶ざっくり)

https://ja.wikipedia.org/wiki/定時飛行場実況気象通報式

NOAA(アメリカ海洋大気庁)などが、このデータをAPIとして取得できるようにしているので、それを取得して、Alexaに喋らせるようなシステムを作ろうかと思っています。
しかし、データ自体、ある程度はリアルタイムであるものの、一定時間は変わらないので、毎回取りに行くのは無駄かなと思いまして、以下のような仕組みにしようと思っています。

  • EventBridgeのcron起動で、定期的にLambda使って、情報を取得し、CSVファイルにしてS3に保存
  • API経由もしくはLambdaを直接実行して、CSVの内容を返却

ここまで考えた時に、CSV貯めておいておけば、それを使って、機械学習の勉強とかできるんじゃないかな、その場合CSVじゃなくて、Apache Parque形式にしておけば、Athenaとかで読み取るときにもいいな。
と思いまして、これまた定期的に、CSVをApache Parqueに変換するバッチを追加することにしました。
注1) AWS Certified Data Analytics – Specialty(DAS)の勉強生きてる?(2度落ちてますが)
注2) 費用のことは考えてない

そんな中、会社のMacがApple M1搭載になるらしく、本格導入前の人柱(笑)に選ばれまして、
M1 Macbook Air 2020が我が家にやってきました。(本当はProとかMaxがいいんですが・・・w)
armコアかーと思った時に、AWS Lambdaって、arm64(AWS Graviton2プロセッサ)対応してたな。
csvからApache Parqueに変換するときの速度って、IntelCPU変わってくるのかな?・・・よし、調べてみよ。
というのが、今回のお話です。

https://aws.amazon.com/jp/blogs/news/aws-lambda-functions-powered-by-aws-graviton2-processor-run-your-functions-on-arm-and-get-up-to-34-better-price-performance/

前置き長すぎ

結論から先に書くと、
arm64の方が処理時間短かったです。

Lambda構築

今回動作している関数のコードについては、先人の方の英知をほぼ使わせていただきました。

https://dev.classmethod.jp/articles/20210323-aws-lambda-with-pyarrow-300/

やってみた記事を含めて、ほんとお世話になっております。(実は競合他社さんなのですが)

最近開発はなるべく、VS CodeのRemote Container上でやると決めているので、今回も同様に。
使うコンテナは、x86_64とarm64に対応していて、Lambdaとも相性の良さそうなAmazon Linux2用のコンテナを使います。
デプロイについては、最近AWS CDKを使っているのですが、
参考記事にもあるように、変換に使うpyarrowはLambda Layerにした方が良いので、その辺を考慮して、
CDKはv1.x系のaws-lambda-pythonを使おうと思いました(過去形なのは後述)
そういえば、全部込みでコンテナイメージでデプロイしても良かったなと今更気づく人です。

最終的なDockerfileはこんな感じですが、試行錯誤した結果なので、いらないところもあります。

Dockerfile
FROM amazonlinux:latest

RUN amazon-linux-extras install -y

RUN yum update -y && yum install systemd tar unzip sudo docker -y
RUN yum install -y gcc gcc-c++ kernel-devel python-devel python3-devel libxslt-devel libffi-devel openssl-devel bzip2-devel libffi-devel wget zip tar gzip make
RUN curl --silent --location https://rpm.nodesource.com/setup_14.x | sudo bash -
RUN sudo yum -y install nodejs
# RUN sudo amazon-linux-extras install -y python3.9

RUN cd /opt && \
    wget https://www.python.org/ftp/python/3.9.8/Python-3.9.8.tgz && \
    tar xzf Python-3.9.8.tgz && \
    /opt/Python-3.9.8/configure --enable-optimizations && \
    make altinstall && \
    rm -f /opt/Python-3.9.8.tgz && \
    python3.9 -m pip install --upgrade pip

RUN echo 'alias python=python3.9' >> ~/.bashrc
RUN echo 'alias pip=pip3.9' >> ~/.bashrc
RUN source ~/.bashrc

RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    && unzip awscliv2.zip \
    && sudo ./aws/install

# create user
RUN useradd "ec2-user" && echo "ec2-user ALL=NOPASSWD: ALL" >> /etc/sudoers

とりあえず今のところは、Intel Macがメイン機なので、まずはx86_64用のLayerと関数を用意。
デプロイ後、問題ないことを確認したところで、
DockerfileなどをM1 Mac側に移植し、arm64用のLayerと関数を用意して、
それぞれファイル変換してみました。
なお、そこに至るまでにいろいろありましたが、それは後述。

検証結果

検証は、それぞれ1回コールドスタートさせてから、5回ファイルを変換させています。

データはとりあえず一旦検証用なので、何かないかなー。と探したところ、飛行機つながりで、サンフランシスコ国際空港の航空会社別月次旅客輸送統計に関する報告書なるものがあったので、それを使うことにしました。
ファイルサイズは4.6Mほど。

https://catalog.data.gov/dataset/air-traffic-passenger-statistics

検証には、上記サイトからダウンロードしてきたオリジナルデータそのまま(4.6M)と、そのファイルの中身をコピーしまくって作った102Mのファイルで行っています。

オリジナルデータ(4.6M)を処理

Lambdaの設定 : メモリー256M タイムアウト60秒

アーキテクチャ 最短処理時間(ms) 最長処理時間(ms) 平均処理時間(ms)
x64_86 1955.02 2143.26 2044.512
arm64 1699.73 1859.65 1763.528

arm64のほうが15%ぐらい処理時間短いみたいですね。

Cloudwatch Logs

x86_64
2021-12-24T10:16:45.848+09:00	START RequestId: 896066e9-45ad-477c-b473-843dd811be24 Version: $LATEST
2021-12-24T10:16:49.151+09:00	END RequestId: 896066e9-45ad-477c-b473-843dd811be24
2021-12-24T10:16:49.151+09:00	REPORT RequestId: 896066e9-45ad-477c-b473-843dd811be24 Duration: 3302.06 ms Billed Duration: 3303 ms Memory Size: 256 MB Max Memory Used: 166 MB Init Duration: 839.09 ms
2021-12-24T10:18:16.573+09:00	START RequestId: 63372e34-0a82-4118-ab66-897c01cbcc75 Version: $LATEST
2021-12-24T10:18:18.717+09:00	END RequestId: 63372e34-0a82-4118-ab66-897c01cbcc75
2021-12-24T10:18:18.717+09:00	REPORT RequestId: 63372e34-0a82-4118-ab66-897c01cbcc75 Duration: 2143.26 ms Billed Duration: 2144 ms Memory Size: 256 MB Max Memory Used: 171 MB
2021-12-24T10:18:58.486+09:00	START RequestId: abccb6b5-22b6-47aa-ba0f-ecc5f0f4a4c8 Version: $LATEST
2021-12-24T10:19:00.510+09:00	END RequestId: abccb6b5-22b6-47aa-ba0f-ecc5f0f4a4c8
2021-12-24T10:19:00.510+09:00	REPORT RequestId: abccb6b5-22b6-47aa-ba0f-ecc5f0f4a4c8 Duration: 2019.80 ms Billed Duration: 2020 ms Memory Size: 256 MB Max Memory Used: 171 MB
2021-12-24T10:19:30.672+09:00	START RequestId: b755148b-8fba-41d1-8d74-52685a5cf0de Version: $LATEST
2021-12-24T10:19:32.630+09:00	END RequestId: b755148b-8fba-41d1-8d74-52685a5cf0de
2021-12-24T10:19:32.630+09:00	REPORT RequestId: b755148b-8fba-41d1-8d74-52685a5cf0de Duration: 1955.02 ms Billed Duration: 1956 ms Memory Size: 256 MB Max Memory Used: 171 MB
2021-12-24T10:20:09.746+09:00	START RequestId: 68e08b99-4317-48cc-898d-dbc754826197 Version: $LATEST
2021-12-24T10:20:11.870+09:00	END RequestId: 68e08b99-4317-48cc-898d-dbc754826197
2021-12-24T10:20:11.870+09:00	REPORT RequestId: 68e08b99-4317-48cc-898d-dbc754826197 Duration: 2120.55 ms Billed Duration: 2121 ms Memory Size: 256 MB Max Memory Used: 174 MB
2021-12-24T10:20:51.827+09:00	START RequestId: 74a5ce2f-5a31-4c30-85ee-a5f726fbdd0b Version: $LATEST
2021-12-24T10:20:53.822+09:00	END RequestId: 74a5ce2f-5a31-4c30-85ee-a5f726fbdd0b
2021-12-24T10:20:53.822+09:00	REPORT RequestId: 74a5ce2f-5a31-4c30-85ee-a5f726fbdd0b Duration: 1983.93 ms Billed Duration: 1984 ms Memory Size: 256 MB Max Memory Used: 174 MB 
arm64
2021-12-24T10:16:47.844+09:00	START RequestId: f4fee60b-9400-4225-be19-86334abcda9e Version: $LATEST
2021-12-24T10:16:50.860+09:00	END RequestId: f4fee60b-9400-4225-be19-86334abcda9e
2021-12-24T10:16:50.860+09:00	REPORT RequestId: f4fee60b-9400-4225-be19-86334abcda9e Duration: 3015.01 ms Billed Duration: 3016 ms Memory Size: 256 MB Max Memory Used: 165 MB Init Duration: 681.92 ms
2021-12-24T10:18:23.312+09:00	START RequestId: cca3a5a9-7598-4f76-bc5f-89d2a808fb90 Version: $LATEST
2021-12-24T10:18:25.013+09:00	END RequestId: cca3a5a9-7598-4f76-bc5f-89d2a808fb90
2021-12-24T10:18:25.013+09:00	REPORT RequestId: cca3a5a9-7598-4f76-bc5f-89d2a808fb90 Duration: 1699.73 ms Billed Duration: 1700 ms Memory Size: 256 MB Max Memory Used: 169 MB
2021-12-24T10:18:46.542+09:00	START RequestId: b08534fa-d521-4e2e-bef4-d3df906f633b Version: $LATEST
2021-12-24T10:18:48.301+09:00	END RequestId: b08534fa-d521-4e2e-bef4-d3df906f633b
2021-12-24T10:18:48.301+09:00	REPORT RequestId: b08534fa-d521-4e2e-bef4-d3df906f633b Duration: 1754.35 ms Billed Duration: 1755 ms Memory Size: 256 MB Max Memory Used: 169 MB
2021-12-24T10:19:28.511+09:00	START RequestId: 0ceaa3a1-b120-4750-b950-0accf940bb44 Version: $LATEST
2021-12-24T10:19:30.299+09:00	END RequestId: 0ceaa3a1-b120-4750-b950-0accf940bb44
2021-12-24T10:19:30.299+09:00	REPORT RequestId: 0ceaa3a1-b120-4750-b950-0accf940bb44 Duration: 1783.69 ms Billed Duration: 1784 ms Memory Size: 256 MB Max Memory Used: 170 MB
2021-12-24T10:20:03.435+09:00	START RequestId: 9fac6120-a1ed-47ed-8982-f770ad3fee67 Version: $LATEST
2021-12-24T10:20:05.299+09:00	END RequestId: 9fac6120-a1ed-47ed-8982-f770ad3fee67
2021-12-24T10:20:05.299+09:00	REPORT RequestId: 9fac6120-a1ed-47ed-8982-f770ad3fee67 Duration: 1859.65 ms Billed Duration: 1860 ms Memory Size: 256 MB Max Memory Used: 170 MB
2021-12-24T10:20:42.797+09:00	START RequestId: 5c85a06c-96da-4429-a574-1ba597ad8c87 Version: $LATEST
2021-12-24T10:20:44.527+09:00	END RequestId: 5c85a06c-96da-4429-a574-1ba597ad8c87
2021-12-24T10:20:44.527+09:00	REPORT RequestId: 5c85a06c-96da-4429-a574-1ba597ad8c87 Duration: 1720.22 ms Billed Duration: 1721 ms Memory Size: 256 MB Max Memory Used: 170 MB

データ増やしたもの(102M)を処理

Lambdaの設定 : メモリー1024M タイムアウト300秒

アーキテクチャ 最短処理時間(ms) 最長処理時間(ms) 平均処理時間(ms)
x64_86 9249.39 10196.84 9762.724
arm64 8756.98 9548.6 9044.856

こちらもarm64のほうが速いですが、5〜7%ぐらいに留まっているようです。

Cloudwatch Logs

x86_64
2021-12-24T10:36:53.388+09:00	START RequestId: b9c627da-cb58-492e-ac64-f16d49178d1e Version: $LATEST
2021-12-24T10:37:03.544+09:00	END RequestId: b9c627da-cb58-492e-ac64-f16d49178d1e
2021-12-24T10:37:03.544+09:00	REPORT RequestId: b9c627da-cb58-492e-ac64-f16d49178d1e Duration: 10154.34 ms Billed Duration: 10155 ms Memory Size: 1024 MB Max Memory Used: 664 MB Init Duration: 744.01 ms
2021-12-24T10:38:26.549+09:00	START RequestId: 09f8d2b1-17d4-4fe6-af6a-b2ed5a77fcc7 Version: $LATEST
2021-12-24T10:38:35.804+09:00	END RequestId: 09f8d2b1-17d4-4fe6-af6a-b2ed5a77fcc7
2021-12-24T10:38:35.804+09:00	REPORT RequestId: 09f8d2b1-17d4-4fe6-af6a-b2ed5a77fcc7 Duration: 9249.39 ms Billed Duration: 9250 ms Memory Size: 1024 MB Max Memory Used: 750 MB
2021-12-24T10:39:36.193+09:00	START RequestId: 09912940-cd4b-4c3f-8282-eec9688e1f3a Version: $LATEST
2021-12-24T10:39:45.982+09:00	END RequestId: 09912940-cd4b-4c3f-8282-eec9688e1f3a
2021-12-24T10:39:45.982+09:00	REPORT RequestId: 09912940-cd4b-4c3f-8282-eec9688e1f3a Duration: 9784.97 ms Billed Duration: 9785 ms Memory Size: 1024 MB Max Memory Used: 761 MB
2021-12-24T10:40:29.883+09:00	START RequestId: 90d7921a-98d5-4699-93ef-3fd40debefc1 Version: $LATEST
2021-12-24T10:40:39.983+09:00	END RequestId: 90d7921a-98d5-4699-93ef-3fd40debefc1
2021-12-24T10:40:39.983+09:00	REPORT RequestId: 90d7921a-98d5-4699-93ef-3fd40debefc1 Duration: 10097.97 ms Billed Duration: 10098 ms Memory Size: 1024 MB Max Memory Used: 761 MB
2021-12-24T10:41:29.187+09:00	START RequestId: 9f210e6e-8dd4-4d77-ae65-fc5d6aecf483 Version: $LATEST
2021-12-24T10:41:38.677+09:00	END RequestId: 9f210e6e-8dd4-4d77-ae65-fc5d6aecf483
2021-12-24T10:41:38.677+09:00	REPORT RequestId: 9f210e6e-8dd4-4d77-ae65-fc5d6aecf483 Duration: 9484.45 ms Billed Duration: 9485 ms Memory Size: 1024 MB Max Memory Used: 771 MB
2021-12-24T10:42:29.258+09:00	START RequestId: de106a36-25d9-4aaf-805e-ab60571e957e Version: $LATEST
2021-12-24T10:42:39.458+09:00	END RequestId: de106a36-25d9-4aaf-805e-ab60571e957e
2021-12-24T10:42:39.458+09:00	REPORT RequestId: de106a36-25d9-4aaf-805e-ab60571e957e Duration: 10196.84 ms Billed Duration: 10197 ms Memory Size: 1024 MB Max Memory Used: 771 MB
arm64
2021-12-24T10:36:43.594+09:00	START RequestId: 384e0a2a-5e6d-4584-b2f2-08bebfca5677 Version: $LATEST
2021-12-24T10:36:54.212+09:00	END RequestId: 384e0a2a-5e6d-4584-b2f2-08bebfca5677
2021-12-24T10:36:54.212+09:00	REPORT RequestId: 384e0a2a-5e6d-4584-b2f2-08bebfca5677 Duration: 10618.40 ms Billed Duration: 10619 ms Memory Size: 1024 MB Max Memory Used: 658 MB Init Duration: 656.21 ms
2021-12-24T10:38:26.155+09:00	START RequestId: a9d8e262-25c6-49a3-83d6-c785293ca438 Version: $LATEST
2021-12-24T10:38:35.708+09:00	END RequestId: a9d8e262-25c6-49a3-83d6-c785293ca438
2021-12-24T10:38:35.708+09:00	REPORT RequestId: a9d8e262-25c6-49a3-83d6-c785293ca438 Duration: 9548.60 ms Billed Duration: 9549 ms Memory Size: 1024 MB Max Memory Used: 748 MB
2021-12-24T10:39:43.671+09:00	START RequestId: 52f92e7b-3fc7-48d5-bf87-8a8f5c296edf Version: $LATEST
2021-12-24T10:39:52.718+09:00	END RequestId: 52f92e7b-3fc7-48d5-bf87-8a8f5c296edf
2021-12-24T10:39:52.718+09:00	REPORT RequestId: 52f92e7b-3fc7-48d5-bf87-8a8f5c296edf Duration: 9043.41 ms Billed Duration: 9044 ms Memory Size: 1024 MB Max Memory Used: 753 MB
2021-12-24T10:40:36.200+09:00	START RequestId: d79f0b8c-32b6-4c34-8a8b-b829de35af47 Version: $LATEST
2021-12-24T10:40:45.074+09:00	END RequestId: d79f0b8c-32b6-4c34-8a8b-b829de35af47
2021-12-24T10:40:45.075+09:00	REPORT RequestId: d79f0b8c-32b6-4c34-8a8b-b829de35af47 Duration: 8870.75 ms Billed Duration: 8871 ms Memory Size: 1024 MB Max Memory Used: 760 MB
2021-12-24T10:41:36.725+09:00	START RequestId: 8004b2e4-068c-45a9-8a1d-41a0b904f2af Version: $LATEST
2021-12-24T10:41:45.732+09:00	END RequestId: 8004b2e4-068c-45a9-8a1d-41a0b904f2af
2021-12-24T10:41:45.732+09:00	REPORT RequestId: 8004b2e4-068c-45a9-8a1d-41a0b904f2af Duration: 9004.54 ms Billed Duration: 9005 ms Memory Size: 1024 MB Max Memory Used: 762 MB
2021-12-24T10:42:35.187+09:00	START RequestId: b979bca3-d3b3-4398-ae4a-c795d5d68ba8 Version: $LATEST
2021-12-24T10:42:43.945+09:00	END RequestId: b979bca3-d3b3-4398-ae4a-c795d5d68ba8
2021-12-24T10:42:43.945+09:00	REPORT RequestId: b979bca3-d3b3-4398-ae4a-c795d5d68ba8 Duration: 8756.98 ms Billed Duration: 8757 ms Memory Size: 1024 MB Max Memory Used: 773 MB 

このような結果でした。arm64つまりGravitonプロセッサなかなかやるなという感じです。

試行錯誤の記録

今回、途中色々ハマったりもしたので、その辺をまとめておきます。

AWS CDKでデプロイしようとしたけどハマる

なぜか、cdk diff 等のコマンドを実行するとエラー。
spawnSync docker ENOENT
ああ、esbuildがいるのね。とインストールして再度実行しても、ダメ。
コンテナ変えてもだめ。
小1時間悩んだところで、今回はCDKを諦めました。これは別途課題です。
なお、CDKがらみもあり、Python3.7にしてました。

Python3.7で作ってみた

機を取り直して、
Layer用のディレクトリ作って、
pip3 install -t ./python pyarrow
で、pyarrowを配置して、そのフォルダごと圧縮します(記事そのままです)。

その圧縮ファイルをLayerとしてデプロイ。
で、Python3.7のLambda関数を作って(記事ほぼそのままです。ヘッダーをサンプルデータに合わせた暗い)・・・いざサンプルデータをアップロードして、S3トリガー発動。
うまくいった。
では、arm64作りますかで、気づく。
Python3.7ランタイム arm64対応してない

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-runtimes.html

Pythonだと3.8以降になるんですね。
ちなみに普段多用しているNode.jsはv12.x以降。
最新の方を使えってことですね。
ってことで、コンテナのでPythonのバージョンを3.8に変えて、
再度Layerから作り直します。

Python3.8で何故かハマる

気を取り直して、コンテナのPythonをPython3.8に変更して、
pyarrowを配置して、Zipで固めて、Layerとしてデプロイ。
関数のランタイムのバージョンをPython3.8に変更して、いざ実行・・・。
エラー?

[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'pyarrow.lib'
Traceback (most recent call last):

どういうことよ・・・。Pythonのバージョンしか変えてないし、ちゃんと合わせてあるよ。
ビルドバージョンまで合ってないとダメなんだっけと思いながら、
この時点で、23日23時すぎということもあり、
悩んでいても仕方がないので、
Python3.9でやろうと思い、以下のサイトを参考に、Dockerfileを修正することに。

https://pointsandlines.jp/server-infra/docker/amazon-linux2-python3

Python3.9で構築

バージョンってそこまで完全に合わせないとダメなんだけと思いつつ、LambdaランタイムのPythonのバージョンを確認した上で、コンテナ起動時にPython3.9.8をビルドしてインストール、
その後、3回目となりますが(厳密にはもっとやってるけど)、pyarrow を配置して、Zipで固めて、Layerとしてデプロイ。
こちらは無論、x86_64版が入ります。
Pythonのバージョンとpyarrowのインストール(x86_64)
コンテナのアーキテクチャ(x86_64)

でもって、LambdaのランタイムをPython3.9に変更して実行!

成功!やったー!!!

続いて、
Dockerfile等をM1 Mac側に移植して、同じように、コンテナ起動時にPython3.9.8をビルドしてインストール。
ちなみに、ふと見てた感覚ですが、ビルドめっちゃ速かったです。ログ取っておかなかったのは失敗。

コンテナ起動したら、x64_64と同じようにpyarrow を配置して、Zipで固めて、Layerとしてデプロイ。

Pythonのバージョンとpyarrowのインストール(arm64)
コンテナのアーキテクチャ(arm64)

ちゃんとarm64版を入れてますね。ちょっと感動した人。

arm64版のLambdaランタイムを用意して、問題ないことを確認。
・・・長かった。(この時点で既に日が変わっていたので、諦めました。ごめんなさい)

その後行った検証の結果は上記の通りです。

まとめ

そこまで大きな差はないものの、arm64速いですね。
実行回数を増やしたり、もっと負荷かかる処理を行うと、差が出るのかもしれません。(出ない可能性もあります)
ちょっと冬休み中にまたやってみると思います。

そういや、久々にLayer作りましたが、あのエラーはなんだったのか・・・って感じです。
Layer2つ並ぶ図

M1 Macがメインになると、もしかしたら、積極的にarm64のランタイム使っていくことになるのかなーなんてことを思ってみたりしてます。

Discussion