WebGL-Native: UnityをAOTコンパイルして実行する
 okuoku
okuokuprev: https://zenn.dev/okuoku/scraps/2ebc38f03786f4
next: https://zenn.dev/okuoku/scraps/5777ef80737f27
ここまでで一旦記事にした。
とりあえず起動はする
WebAssemblyとのインターフェースに絞ってネイティブモジュール化してみた。
4コア8スレッドのマシンで試しているので、期待値としてはCPU利用率は12.5%くらいになるはず。それよりも高くなっているのは、Node.JS側のGCが コンカレントGCでマルチスレッド化 されているため。
CPU利用率が高いところはロード中で、ゲームシーンではおおむね10%程度なので、目標は達成できていると言える。ロード中というのは、WebAssemblyのimport / export処理で、これらはまだ ffi-napi で実装されたままなので遅い。 ...というか ffi-napi ってそんなに遅かったのか。。
 okuoku
okuoku例外どうすんのか問題
WebAssembly → JavaScript 呼出し中に発生した例外は、とりあえず(元々のJavaScriptコールバックの)生成元に伝達することにしてみた。
... これが正しいのかは何とも言えないが、EmscriptenはWebAssembly処理を中断するためにJavaScript側で例外を投げるケースがあり、そういうケースはこれで対応できる。
今のところ、WebAssembly MVPでは例外の処理ができず、 setjmp / longjmp はこの方法で実装されているようだ。率直に言ってあんまり健康な気がしない。
 okuoku
okuokusetIntervalの挙動がブラウザとNode.JSで違う問題
WebブラウザのsetIntervalは整数値を返却する。
戻り値
intervalIDは、setInterval()を呼び出して作成したタイマーを識別する、0 ではない正の整数値です。
しかし、Node.JSは整数ではなく Timeout オブジェクトを返却する。
$ node
Welcome to Node.js v14.15.3.
Type ".help" for more information.
> setInterval(function(){}, 1000)
Timeout {
  _idleTimeout: 1000,
  _idlePrev: [TimersList],
  _idleNext: [TimersList],
  _idleStart: 12521,
  _onTimeout: [Function (anonymous)],
  _timerArgs: undefined,
  _repeat: 1000,
  _destroyed: false,
  [Symbol(refed)]: true,
  [Symbol(kHasPrimitive)]: false,
  [Symbol(asyncId)]: 185,
  [Symbol(triggerId)]: 5
}
JavaScriptは動的型付なため、戻り値を消費しなければ問題にならない。しかし、EmscriptenではsetIntervalがWebAssembly側から呼ばれるため、戻り値の型は正確でなければならない ... はずなんだけど、Node.JSのWebAssembly実装はこの差をどうも無視しているっぽい。。
とりあえず setInterval は常に -1 を返すようにしておく。
diff --git a/jstestapp/index.js b/jstestapp/index.js
index acd8229..4ed7602 100644
--- a/jstestapp/index.js
+++ b/jstestapp/index.js
@@ -45,6 +45,13 @@ const storage = require("./storage.js");
 const EmuCanvas = require("./emucanvas.js");
 const WebAssembly = require("./wasmproxy.js");
 
+const orig_setInterval = global.setInterval;
+
+function setInterval(cb, timeout){
+    orig_setInterval(cb, timeout);
+    return -1;
+}
+
 const nav = {};
 const doc = {};
 const wnd = {};