2011年4月23日土曜日

Google ChromeとJavaScriptのタイマー

Chrome(dev)でウェブアプリの類を使っていると、別のタブで作業してから、アプリのタブに戻るといつもなら更新されているはずなのに更新されていないことがよく起きます。
(追記 4/27にChrome 11がStableになったので、stableでも影響を受けるようになります)

なんとなく、アクティブなタブ以外はCPU消費を軽減するためにそういうことをやっているというような記事を読んだ記憶があったので、調べてみました。

まず、Firefox5に関しての記事 たくさんタブを開く人にとってFirefox 5は福音となる…かも をみたことを思いだし読み直してみて、Chromeでやっててもおかしくないと思い調査を継続しました。

ちょっと検索して、Getting smoother animated web content while reducing CPUを見つけました。そこには次のような記述がありました。
In the forthcoming Chrome 11 release, we plan to reduce CPU consumption even for pages that are using setTimeout and setInterval. For background tabs, we intend to run each independent timer no more than once per second. 
Chrome devを使っているので、この影響を受けたのは間違いなさそう。いずれ他のブラウザでもそのうち影響が出てきそうです。

これはタイマーの使い方によっては影響の度合いは違いますが、それなりに影響が出てきそうです。
タイマーの数を節約するために、最も短い間隔で発生させたいイベントの間隔とか最大公約数的にイベントを発生させて、そのイベントハンドラ内でイベントディスパッチしたりすることがあります。
これの実現方法に、どのイベントを起こすかの制御にカウンターを使っていると、イベントの発生回数が減り、カウンタの変化が遅くなるため、イベントの発生タイミングが大きくずれることになります。

簡単なテストを書いてみて確認しました。タイマーのイベントハンドラで、イベント発生回数と時間ベースで、表示を更新するというものです。
前面に表示している間はほぼ同じ速さで数字が増えていくのに対して、裏に回すと時間ベースの方はあまり影響を受けないの対して、イベント発生回数によるほうはどんどん遅れていきます。

イベント発生回数による処理
if (++cnt % 5 === 0) {
    c = $('#counter1');
    c.text(parseInt(c.text()) + 1);
}

時間ベースの処理
var now = Date();
if (now > next) {
    c = $('#counter2');
    c.text(parseInt(c.text()) + 1);
    next = now + 1000;
}

0 件のコメント:

コメントを投稿