WebGL-Native: Duktapeに移植したい
prev: https://zenn.dev/okuoku/scraps/efa3e214ee8348
next: https://zenn.dev/okuoku/scraps/b4b12919554ab0
Duktape
DuktapeはシングルソースのJavaScriptインタプリタで、完全なJavaScriptを実装しつつマイコンのような環境でも実行できるので人気がある。
他にもQuickJSやHermes等組込みJavaScriptエンジン自体には相当量の選択肢があるが、組込みが容易で、かつ、そこそこのパフォーマンスを提供するのでDuktapeを選んだ。というかQuickJSやHermesが割とこの手のインタプリタとしては高速といっても、Duktapeの2〜10倍くらいしか高速でないので、Duktapeで実用的なパフォーマンスが出ないなら他の処理系でも厳しいと考えざるを得ない。
(ちなみにV8のJITは現状の用途だとDuktapeの10〜100倍高速になると考えている -- 良いインライン化があるのが大きい)
DLL読み取り機能の移動
DLLの読み込みのために ffi-napi
を使いっぱなしだったので、 ffi-napi
のソースコードに含まれるパブリックドメインなWin32向け dlopen
実装を使って自前で持つことにした。
これにより、プロジェクトは一切JavaScript的な外部ライブラリに依存しなくなった(正確には async
/ await
のランタイムはfacebookのを使ってるけど)。
基本ライブラリの組込み
... 基本ライブラリをDLLで供給していると、DLLの読み取り機能のために基本ライブラリが使えなくなっちゃうので、基本ライブラリは処理系の NCCC 実装が直に供給することにした。
動いた
とりあえず setInterval
とか足りないものは適当に埋めて動かしてみた。
... うーむ。。絶妙に遅い。ゲームができないレベルではないが。。少くともDebugビルドはちょっと不味い感じの遅さで評価に使うにはReleaseビルドでないと辛い。
特に2Dアプリが遅い
手元のサンプルではDOSbox-xが特に動作速度を守れないレベルで遅くなっていた。VisualStudioのプロファイラで確認してみると、
SDL_UpdateWindowSurfaceRects
で時間を喰っているのがわかる。これは(少くとも当時の)Emscriptenでは JavaScript上でビットマップをコピー していて処理量がO(n^2)オーダとなっているため、インタプリタでは劇的に遅くなってしまう。
まぁこれに関してはWebGLを使ってねということで。。
めも
-
https://duktape.org/api.html#duk_push_current_function
duk_push_current_function
の存在に気付くのに小一時間掛かった。コンテキストオブジェクトへのポインタをJavaScript的なクロージャに覚えさせるためにfunction(){}[0] = context
的に使っている。 - リファレンスページのページ内検索を
.
で始めると必ずリファレンスがヒットするようになっているのがかしこい。CSS的に隠すことで実現している。
<a href="#duk_push_c_function"><span class="hidechar">.</span>duk_push_c_function()</a>