JavaScript でコマンドラインアプリを書く時もイベントループを無視したらダメ(なことがある)という話

先日書いた電卓に関して、そのための十進演算ライブラリのテストを書いていてはまった、という話。

一般に JavaScript によるブラウザアプリはイベントドリブン型で書かないといけないわけだが、総当たりチェックのコマンドラインアプリを作り Node.js で実行していたところ、端末(tty)やパイプに write で文字列を大量に出力すると(ループのネストが深いと顕著?)GC を実行してもどんどんプロセスのメモリサイズが大きくなってゆくのに気付いた。

ほぼ同じ問題に当たった人による issue がこちら https://github.com/joyent/node/issues/3648 にあるのだが、イシューの題に「in a single tick」とあるように、イベントループを回していないことが原因で、バグ的な理由によるリークではありません、というのが結論だと教えていただいた。

というわけで、( Node.js の場合)コマンドラインアプリでも for (;;) { ... } で最外のループを回したりして制御を手放さないのはダメで、

var loop = function () {
	main()
	setImmediate(loop)
}
loop()

のようにして、適度な粒度でイベントハンドラとして走らせる必要がある。