setTimeoutとJavaScriptのスレッド

amachangさんのsetTimeoutに関する記事とコメントを読んだら気になったので、setTimeoutとブラウザでのJavaScriptについて調べてみた。

setTimeoutには現在のところ明確な仕様はないようである。ただし、Web Applications 1.0のドラフトによれば、複数のスクリプトが同時に実行されることはなく、シングルスレッドでスクリプトが実行されるようだ。

Timeouts must never fire while another script is executing. (Thus the HTML scripting model is strictly single-threaded and not reentrant.)

従って、この仕様に従うブラウザに対しては、amachangさんの指摘は正しいと思う。

ただ、個人的にはスクリプトがシングルスレッドで動作するというモデルよりは、ブラウザ環境はマルチスレッドで動いていて、ただし、スクリプトの実行はアトミックな処理とするモデルの方がしっくりくる。

おそらく、ブラウザ環境では、画面描画スレッドやイベント処理スレッドが用意されていて、これらのスレッドとスクリプト実行スレッドが協調して動作している。そして、殆どのブラウザでは、スクリプトの実行はアトミックな処理とされている。つまり、スクリプトの実行中は画面描画やイベント処理は実行されない。その為、処理時間のかかるスクリプトを実行すると、描画スレッドやイベント処理スレッドが実行されないので、画面が固まってしまい、レスポンスが低下する。

このレスポンス低下の問題を回避するには、処理時間のかかるスクリプトの実行を、複数のスクリプトの実行に分割すれば良い。このことを実現するのにsetTimeoutが使える。つまり、

heavyFunction1()
heavyFunction2()

という処理を、

heavyFunction1()
setTimeout(heavyFunction2, 10)

とすると、重いアトミックな処理が、複数のアトミックな処理に分割される。その為、処理の間に描画スレッドや、イベント処理スレッドが割り込めるようになり、レスポンスが向上する可能性がある。