2017年2月25日土曜日

setIntervalの精度は間隔の長さに比例する

精度はあまり良くないということは聞いたことがありましたが、実際にどういう感じなのか知らなかったのでサンプルを作って動作確認しました。

結論としては間隔が短いほど精度が悪化していきます。
あと、定期的に実行するfunctionが処理に要する時間に応じて精度が落ちていく、というか次の実行までの間隔が伸びていくので、setIntervalを実行した瞬間から計算して「このタイミングで何回目の処理が行われる」の時刻からどんどん遅れていくことになります。

実験用ソース
<html>
<title>シングルループ</title>
<body>
<input id=inp value=100>
<button id=btn0>開始</button>
<button id=btn1>停止</button>
<button id=btn2>objIV</button>
<div id=div></div>
</body>
<script>
resizeTo(800,150)
objIV = 0
btn0.onclick=function(){
btn1.onclick()
var st=(new Date()).getTime(), 回数=0, キリ='', 間隔=inp.value-0, 計算上=''
objIV = setInterval(function(){
var nt=(new Date()).getTime()
div.innerText = (nt - st) + 'ミリ秒経過\n' + キリ + '\n' + 計算上
if((++回数 % 10)==0){
キリ = 回数+'回目:'+((nt-st) / 回数 / 間隔)
計算上 = '計算とのズレ=nt('+nt+') - (st('+st+') + 間隔('+間隔+') * 回数('+回数+')) = '+(nt-(st+間隔*回数))
}
}, 間隔)
}
btn1.onclick=function(){ objIV && clearInterval(objIV) }
btn2.onclick=function(){ confirm(objIV) }
</script>
</html>
view raw setInterval.hta hosted with ❤ by GitHub


動作結果







私のPCでは間隔を1000msにすると、だいたい1010msぐらいの間隔で実行されました。
丸一日分に相当する回数を実行するのにかかる時間は1.01日間=24.24時間=1454分で、14.4分余計に時間がかかるということで、それが問題になるかどうかは処理の内容によりますが、処理負荷がほぼ最低でこれだけズレるということは記録しておこうと思いました。

2 件のコメント:

  1. こんにちは。質問なのですが、setIntervalのループ時間を0.5ぐらい(単位はつけていません)にするとCPU結構使いますか?

    返信削除
  2. ご質問ありがとうございます。

    intel i7-6700 @ 3.40GHzで以下のソースを動作確認してみました。

    <html>
    <body></body>
    <script>
    var test = function(){
    document.body.innerText = 'テスト中…'
    var g = function(){return (new Date()).getTime()}
    var 開始 = g()
    var 分 = 1
    var 間隔 = 0.5

    var 計算上の回数 = 分 * 60 * 1000 / 間隔
    var 実際の回数 = 0

    setInterval(function(){ 実際の回数++ }, 間隔)

    setTimeout(function(){
    document.body.innerText = '計算上の回数:'+計算上の回数+'\n実際の回数:'+実際の回数
    }, (分+1) * 60 * 1000)
    }
    test()
    </script>
    </html>

    [間隔0.5の場合の結果]
    計算上の回数:120000
    実際の回数:1

    [間隔を1にした場合の結果]
    計算上の回数:60000
    実際の回数:7665

    処理中のCPU使用率をタスクマネージャのプロセスタブで見てみましたが、上記HTAのCPU使用率は常に0%でした。(パフォーマンスのタブでCPU全体の使用率も見ていましたが、その他プログラムの影響で4~7%程度の範囲で波打つ程度でした)
    setIntervalそのもののCPU負荷は高くないと思われます。

    ちなみにsetIntervalの仕様は(ブラウザにもよりますが)下記URLページの通りで
    https://developer.mozilla.org/ja/docs/Web/API/Window/setInterval

    ループ時間を0.5に設定しても、実際には下限値(1、もしくは10など)で動作したり、私の環境のように一回しか実行されなかったりするようです…。

    返信削除