成果物: https://github.com/macoshita/lambda-wasm-example
Lambda が今年の 4 月に Node.js 8.10 に対応した。 8 からはフラグ無しで WebAssembly (WASM) に対応しているので、動くんだろうなーとは思いつつも試してなかったのでやってみた。結論、動く。
構成
.
├── README.md
├── hello_world
│ ├── app.js
│ └── wasm
│ ├── hello_world_wasm.d.ts
│ ├── hello_world_wasm.js
│ ├── hello_world_wasm_bg.js
│ └── hello_world_wasm_bg.wasm
├── hello_world_wasm
│ ├── Cargo.lock
│ ├── Cargo.toml
│ ├── build.sh
│ ├── package.json
│ └── src
│ └── lib.rs
└── template.yaml
hello_world_wasm をビルドして、成果物を hello_world の中に出力し、 hello_world を AWS Lambda にデプロイする。
プロジェクト全体は AWS SAM CLI で作っていて、 Rust 部分は wasm-bindgen の Basic Usage をやってるだけ。
Rust 側
受け取った文字列に Hello をつけるだけ。
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
# [wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
ビルドスクリプトは こちら 。ポイントは下記のコマンドで --nodejs
をつけていること。
$ wasm-bindgen target/wasm32-unknown-unknown/debug/hello_world_wasm.wasm --nodejs --out-dir ../hello_world/wasm
Node.js 側
Rust 側が吐き出した以下の js 群を……
├── hello_world
│ ├── app.js
│ └── wasm
│ ├── hello_world_wasm.d.ts
│ ├── hello_world_wasm.js
│ ├── hello_world_wasm_bg.js
│ └── hello_world_wasm_bg.wasm
JS 側で require して使う。
const wasm = require('./wasm/hello_world_wasm')
exports.handler = async event => {
return {
'statusCode': 200,
'body': JSON.stringify({
message: wasm.greet('rust!!!')
})
}
}
Node.js 8 に対応した Lambda だと、すごくスッキリかけるようになっていた。よい。
ローカルで動作確認
Docker が入っていれば、下記のコマンドでローカルで Lambda を試すことができる。
$ sam local start-api
http://127.0.0.1:3000/hello にアクセスすると、以下のような JSON が返される。 WASM が動いた。
{"message":"Hello, rust!!!!"}
用途
Lambda は Go を使えば速度も申し分ないし、そこまで使い所はないんだろうなーと思いつつ、以下が思いついたところ。
- 既存の Lambda の一部だけを早くしたい
- 一番ありそう
- シングルバイナリ生成が面倒 or バカでかくなる言語で Lambda 書きたい
-
https://github.com/appcypher/awesome-wasm-langs とか見てると結構ありそう
- てか下手すると Java とか Python は WASM にして動かしたほうが早いんじゃ?
-
https://github.com/appcypher/awesome-wasm-langs とか見てると結構ありそう
- バイナリ生成して exec で呼び出すよりは WASM のサンドボックス内にあるから安全かも
- かも
これはというのがあったら教えて欲しい。