Edited at

AWS Lambda で WebAssembly を動かす

More than 1 year has passed since last update.

成果物: 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 書きたい



  • バイナリ生成して exec で呼び出すよりは WASM のサンドボックス内にあるから安全かも


    • かも



これはというのがあったら教えて欲しい。