js_of_ocamlとCoreの相性について

Posted on June 8, 2014

結論を先に述べると、js_of_ocamlとCoreの相性は、少なくとも現時点では、あまりよくない。その理由は以下である。

js_of_ocamlによる変換に時間がかかる

例えば、こんな小さなコードでも、

(* a.ml *)
open Core_kernel.Std

let () = List.iter ~f:print_int [1; 2; 3]

バイトコードはかなり大きくなる。

$ ocamlfind ocamlc -package core_kernel -linkpkg a.ml
$ ls -lh a.out
-rwxr-xr-x 1 tomo tomo 2.1M  6月  8 22:30 a.out

このバイトコードをjs_of_ocamlで変換すると、

$ js_of_ocaml a.out  7.80s user 0.18s system 99% cpu 7.981 total

ぐらい時間がかかる。

Batteries Includedのように、packせずに各モジュールを提供してくれればもう少し対応の余地があると思う。

変換後のJavaScriptのコードサイズが大きい

変換後のJavaScriptのコードサイズはこれぐらいになる。

$ ls -lh a.js
-rw------- 1 tomo tomo 832K  6月  8 23:04 a.js

さらにClosure Compilerをかけると逆に大きくなる。

$ time closure-compiler a.js >! a.opt.js
closure-compiler a.js >| a.opt.js  31.72s user 0.26s system 194% cpu 16.420 total
$ ls -al a.opt.js
-rw-r--r-- 1 tomo tomo 855K  6月  8 23:05 a.opt.js

32bit版OCamlを使う必要がある

core_kernelのlib/pool.mlが、OCaml処理系のアーキテクチャに依存して実装を分岐しており、その結果js_of_ocamlのランタイムと衝突を起こしてしまっている。というのも、js_of_ocamlは32bitのワードサイズを想定しているため、64bit版OCamlでコンパイルされたcore_kernelをjs_of_ocamlで利用すると、ワードサイズの不一致により想定外の動作になるからだ1

というわけでCoreを利用したOCamlコードをjs_of_ocamlで変換するには、最低でも32bit版OCamlを使う必要がある。

確認環境


  1. 実際は110行目のassertで異常終了する