All Articles

(続々) LuaをWebAssemblyにコンパイルして実行する話

(続きの続き) LuaでもWebAssemblyがしたかった

前回の続きです。

実行速度を改善した

前回では関数をコールするたびにlua_Stateを生成していたのですが、初期化段階でlua_Stateを生成してスクリプト本体を読み込み、関数内ではそのstateを参照しつつ実行することで実行速度が現実的なレベルになりました。具体的には、

EMSCRIPTEN_KEEPALIVE
const char* hello_world() {
    // Create new state
    lua_State* L = luaL_newstate();
    // load compiled program
    boot_lua(L);

    // Call Lua function
    lua_pcall(L);
    ...
    // close
    lua_close(L);
}

と関数毎にやっていたのを、

// global state
static lua_State* wasm_lua_state = NULL;

EMSCRIPTEN_KEEPALIVE
const char* hello_world() {
    // Call Lua function
    lua_pcall(wasm_lua_state);
}

int main(void) {
    // Create new state at global
    wasm_lua_state = luaL_newstate();
    // load compiled program
    boot_lua(wasm_lua_state);
    return 0;
}

としました。main()はWASMがコンパイルされるタイミングで実行されるようなので、ここで初期化して使い回すことで関数のコールは劇的に速くなりました。まぁ当たり前といえば当たり前でしょうけど…。

グローバル変数は良い作法ではないと思ってますが、.cファイル自体が自動生成なのでとりあえず他からCのロジックが入る余地はなさそうで、また関数の終了時にluasettop(wasmlua_state, 0)としてstackを必ずクリアしているので問題なさそう(あったら教えてください)

あとlua_close()をする場所がなかったので記述していないですが、WASMってブラウザがnavigationした時に解放するんですかね。ちょっとよくわかってないです。

現場からは以上です。