setTimeoutとOSのタイマーレゾリューション

ソース側は読んでも前に調べた以上のことはよくわかりませんでした。

実験のほう。
zarame.com/zide/ 日記(2005-11-24) Windows IE JavaScript のタイマーは精度が悪いは平均値を測っているので、タイマのレゾリューションが見えなくなっちゃうので、ヒストグラムをとりました。手動で。そのうちまじめにとりたい。

if ( !window.dist )
 dist = {};

var t1 = new Date();
    var id = setTimeout( function () {
        var  t2 = new Date();
        var diff =  (
          ( t2.getUTCMilliseconds() - t1.getUTCMilliseconds())+ 1000) % 1000;
        clearTimeout(id);
        dist[diff] = dist[diff] ? dist[diff] + 1 : 1;
    }, 0);

dist

というのをfirebugコンソールに書いてRunボタンを押し捲ります。
Nmsのtimeoutで実行して、ほんとはどれくらいあとに実行されてるのかの分布を調べようというわけです。

Dateで取れる日付が何を基準に作られていていつ更新されてるのかを知らないと意味ないけど、とりあえずそこはおいておいて。


以下何回か押し捲った結果。

0ms on Windows

Object 16=47 15=28 0=6 32=3 31=7

Windowsは0msにするとほんとに0msで呼び出されることがあります。
UI thread -> Timer thread -> UI thread のスイッチが0msでできるということになるので、時間の割り当て方がプロセス単位になっててプロセスの持ってる時間が0になるまではずっと実行できるということ?
うちかえったら inside windows 読みます。載ってるかな。

はじめ16msってほんとー?って思ってたのですが、結果からは明らかにWindowsは16msに何か隠されてる!

10ms on Windows

0ms以上(なにかがある)16ms以下で10msの場合。

Object 16=39 31=1 32=2 15=11 0=19

windowsはタイマのレゾリューションが16msみたいで16ms単位でしかタイマがfireしません。10msにしても0msで帰ってくることがあるのは10msが16msより短いから、内部時間のタイミングによるんだと思います。
0ms~16msの間を全部とって、0msで帰ってくる確率の統計を出したら手がかりがつかめると思います。

20ms on Windows

16ms以上の20msの場合。

Object 31=38 16=12 32=7 15=3

予想通り。

0ms on OSX

Object 10=19 32=2 7=2 8=6 26=1 22=4 13=2 35=1 15=2 33=4 17=2 19=2 28=1 14=2 9=9 20=13 38=1 34=1 21=6 29=1 42=1 41=4 30=1 43=1 11=4 4=1 12=1

OSXはかなり値がばらつきます。
よく見るとOSXは10msになりかありそうです。

15ms on OSX

というわけで15msにしてみると

Object 15=58 20=2 16=14 17=4 13=3 22=1 14=12

ちゃんと15msで帰ってくる!

20ms on OSX

20msにすると

Object 19=10 18=4 20=33 21=7 24=1

やっぱり20msで帰ってきます。

17ms on OSX

素数の17msにすると

Object 7=1 16=19 17=18 18=5 27=1 24=1 15=4 26=1 31=1 14=1

7msで帰ってきたりするのが不思議ですが基本17msで帰ってきます。

まとめ

たしかにwindowsはタイマのレゾリューションが(たぶん)16msみたいです。うへー。

OSXは0のときの挙動がいまいち理解できませんが少なくとも1ms単位のようです。


LinuxはOS管理のタイマは4msとカーネル本に明記されていたのでLinuxでどうなるかためしてみてもらえるとうれしいです。