Edited at

AWS LambdaのRuby、カスタムランタイムで動作している説

AWS LambdaのRubyの実行環境が何で動いているのか気になって軽く使ってみたのでメモ

※2018-12-06追記

コメント欄でカスタムランタイムで動いていることを @JONAO33 さんに教えて頂きました。ありがとうございます!


"The Runtime API is the future of how we’ll support new languages in Lambda. For example, this is how we built support for the Ruby language."

https://aws.amazon.com/jp/blogs/aws/new-for-aws-lambda-use-any-programming-language-and-share-common-components/


Hello worldをして呼び出し時間(課金時間)を簡単にベンチマークしてみた

なお計測前に何回か実行してコールドスタートになるのを回避している


環境


  • Ruby 2.5


検証

以下のコードを使用

def lambda_handler(event:, context:)

puts 'Hello world!'
end

10回試行しそれぞれ課金された時間(Billed duration)を測る。単位はms

32.69

10.87
39.41
3.27
20.45
14.54
38.23
23.63
7.50
27.59

image.png


結果

平均: 21.82ms

中央値: 22.04ms

最小: 3.27ms

最大: 39.41ms

かなりばらつきが大きくLambdaのランタイムとしてgolangを使用した時と似たような挙動となった。

そもそもネイティブのRubyでもHello worldしただけで何十msもかかるわけがない。

$ time ruby -e 'puts "hello"'

hello
ruby -e 'puts "hello"' 0.04s user 0.00s system 98% cpu 0.046 total

ならなぜこんなにかかるのかというとLambdaのランタイムに仕組みがある。

以前からも実は自分でRubyやPHPなどをLambdaで動かそうと思えば自前でバイナリを用意してプロセス間通信でパラメータを渡してあげれば出来たが、今回追加されたカスタムランタイムと同様にRuby 2.5ランタイムも一回OSのパイプを経由していると思われる。

やたらばらつきが大きいのも一度OSのレイヤーに降りているので他のOSリソースにスケジューリングを奪われて実行が遅れているのかもしれない。


Pythonの場合

同様にPythonのHello worldも実行してみた


環境


  • Python 3.6


検証

def lambda_handler(event, context):

print("hello world")

return 'ok'

0.34

0.43
0.52
0.34
0.34
0.34
0.35
0.33
0.35
0.43

image.png

平均: 0.38ms

中央値: 0.35ms

最小値: 0.33ms

最大値: 0.52ms

となった

PythonランタイムはLambdaのコンテナが一度実行されるとしばらくそのコンテナを使いまわしてキャッシュする仕組みになっているため、ランタイムの初期化をスキップ出来る。

OSを経由しないためネイティブに近い速度が出るようになっている

$ time python -c "print(1)"

1
python -c "print(1)" 0.01s user 0.00s system 98% cpu 0.013 total


まとめ

Hello worldのばらつきからLambdaのRubyはカスタムランタイムで動いてる説を推測してみた

他のカスタムランタイムでも同様のランタイム初期化のオーバーヘッドは存在するため、ターンアラウンドタイムが重要になる場合や、オーバーヘッドを超えるような処理でない場合はLambdaに既に最適化されているPythonでサクっと処理するのがいいかもしれない