TOP / 実験室 / Javascript sleep with Java applet.

Javascript sleep with Java applet.

はじめに

Java アプレットを使った sleep 関数の実装です。

Javascript はsleep 関数を持たないので、" Javascript sleep "でインターネット検索をすると擬似 sleep 実装の方法をよく見かけます。しかし、大抵のサイトで紹介しているコードサンプルは、 sleep に見せかけるために、while または for 文を一定時間繰り返して実現させているため、 sleep 実行時に CPU 使用率が 100%近くなり、実質使えないものになっています。そこで、Java アプレットを使ったsleepを検証してみました。

要求

Javascript で CPU使用率の低い sleep 関数の実現が可能かどうか検証してください。

テスト環境

  • Windows XP XP2
  • Firefox 2.0.0.2
  • IE 7
  • Java(JRE = Java実行環境) 1.6.0

実装方法

sleep を実現する方法として思い当たったのが、以下です。

  1. Javascript のみで解決
  2. Java applet による方法
  3. Flash による実装
  4. Ajax などでネットワークを使い、クライアントではなくサーバ上で sleep

最初の実装方法は、よくコードサンプルがインターネット上から見られ、そもそもの問題でもあるので今回実装することはしませんでした。実装するには、どうにかして OS ネイティブな sleep システムコールなどを実行させなければいけないので、他の案としてクライアントへのプラグイン利用率が高い Flash と Java applet を選択しました。Flash はほとんど使ったことがありませんが、多分 Java applet と同様に何らか、システムコールへのインターフェースである関数を持ち合わせてそうなので、候補に上げましたが、今回は実装はしませんでした。Flashにより Java applet より現実的な解を求めることが可能かもしれませんので興味の方は実装検証してみてはいかがと思います。

Java は一番私が触れている言語で、Thread.sleep による OS ネイティブなシステムコールを呼べることも分かっているので今回検証実装してみました。また私のサイトがソフトウェア技術者向けなので、ユーザのブラウザに、Java プラグイン入っている割合は高いのですが、Google Analytics による有効率を見ても、2007/03/01現在、98.87%なところを見て、Flash ではなく Java で実装することにしました。

最後の Ajax などによるネットワークによる方法ですが、サーバ側でCGIなどにより多言語で簡単に sleep を実現できるのですが、インターネット、ローカルなどで通信時間に曖昧さが出過ぎるので、可能性を含めた案としてあげたけれど、実装はしませんでした。

検証

Java appletで実装した sleep を実行するページへ遷移します。

検証結果

Javascript で CPU使用率の低い sleep 関数の実現は可能です。しかし制約があります。今回検証したサンプルでは、Java applet で sleepした後に再描写しようとすると表示できない事が分かりました。例えば、for 文で 3回繰り返し処理を実行している時に、for 文内で sleep を実行した後に、何か描写処理をするような処理が出来ませんでした。ちょうど以下のような場合です。

function run() {
  document.all.begin.innerHTML = "run method start.";
  for (cnt = 0; cnt < 3; cnt++) {
    document.all.outtag.innerHTML = cnt;
        mySleep(1000);
  }
  document.all.end.innerHTML = "run method stop";
}

function mySleep(millis) {
    document.applets[0].sleep(millis);
}

これは、Javascript 実行時のレンダリングのタイミングが問題で発生しているのが分かりました。

Javascript の描写処理は、関数が完了した後に描写処理を実行します。 つまり、上記に書かれているコードでは、run 関数を実行して、innerHTML を使うことで、開始時、for 文処理中、終了時に HTML を書き換えていますが、この書き換え処理は、リアルタイムに画面に反映されず、一度なんらかのバッファに変更が蓄積され、run 関数が完了後(run 関数が実行スタックから抜けた後と思われます。) 、ブラウザへのレンダリング処理が行われます。

Javascript の言語仕様を詳しく調べていないので、仕様であるのか、実装の問題なのかは分かりませんが、少なくともこのサンプルでは、逐次再描写を行うことはできないが、CPU使用率の低い sleep 関数の実現が可能であることは分かりました。

現状の問題点を整理する

果たして、Javascript で sleep しなければいけないのですか?

多くの方が sleep について調べていますが、まず実装の前にこの問題を検討したほうがよい解答が得られると思います。他の言語やプラットフォームで簡単に実装できるのであればそちらを選択したほうが良いでしょう。Javascript に sleep 関数がないので実装して欲しいという考えもあるかもしれませんが、あなたが Firefox などのオープンソースブラウザをカスタマイズして実装しない限り、多分永遠に実装されないでしょう。

Javascript はそもそもブラウザをプラットフォームとした言語です。つまり、HTML や HTTP などWeb関連仕様の上に成り立っています。HTTP 通信後のブラウザレンダリングの補完が第一の目的とした場合、sleep が必要な意味が分かりません。何故ゆえに、少ないデータ転送と高速の描写を求めているのに sleep が必要なのでしょうか?というのが、 Web関連に精通した技術者の答えなのではないでしょうか。

Javascript が普及し仕様も更新され、ブラウザも進化しているのに、今日になっても sleep が実装されていないという事がそれを証明しているようにも思われます。

最後に

以前、Javascript の sleep についてブログに書いたのですが、突起してアクセスが多くなったのでこの記事を書いてみました。お困りの方の力になれば幸いです。



イバラキングへのリンク Get Firefox Valid XHTML 1.1 Apple Darwinへのリンク