KB942840の更新でJScript.DLLが高速になった(IE6/WindowsXP)


Windows XP 用の更新プログラム (KB942840)
で、JScriptエンジンのガベージコレクション(GC)のアルゴリズムが変更されて、
Ajaxをゴリゴリ使っているWebサイトでIE6の体感速度がかなり改善された(JavaScript実行途中で固まることがなくなった)模様。

KB942840

Windows Server 2003 ベースのコンピュータまたは Windows XP ベースのコンピュータで Internet Explorer 6 の JScript を使用する Web ページを表示すると、パフォーマンスの Web ブラウザ低下が発生することがあります。

原因
スクリプトが多くの変数を同時に作成すると、この問題は、発生することがあります。 また、この問題が同じ時刻で解析される一意の多くの値がスクリプトに含まれる場合、発生することがあります。 この問題は JScript エンジンがガベージ コレクションを実行する方法が原因で発生します。

ガベージ コレクション アルゴリズムは、次の値を監視します。• スクリプトでの変数割り当ての番号
・ スクリプトで使用されたリテラル値の数
・ スクリプトで割り当てられた文字列値の合計サイズ
これらの値の閾値が超えられるとき、ガベージ コレクションが発生します。 ガベージ コレクション プロセスは、実行されているスクリプトに割り込みます。 したがって、スクリプトを実行しているそれがガベージ コレクションが完了するまで、中断されます。

KB942840の更新で、C:\WINDOWS\system32\jscript.dll が 5.6.0.8831→ 8834 のバージョンに置き換わりました。

jscript-dll-5608834.png

ということで、更新前と更新後でベンチマークを取ってみました。まず一番目。

(1) JavaScript Speed Test 4.0 – The Real World

Before
Time Difference (seconds): 2.781
After
Time Difference (seconds): 2.703

約3%の微妙な差です。ちなみにこの数値はベンチマークを10回実行したときの最小値を計測結果としています。

(2) Javascript Speed Test 2007 (Celtic Kane)

次にid:ZIGOROuさんから教えてもらったJSベンチマークなのですが、IE6ではそのまま動かないので、XHRの関数を一度ブックマークレット経由で定義するなどしてから実行ボタンを押す必要がありました。

javascript:function XMLHttpRequest(){return new ActiveXObject("Microsoft.XMLHTTP");}
Before After
更新前 更新後

またこれも微妙な差です。

(3) JavaScript speed test (jorendorff.com)

JavaScriptの構文毎に詳しいベンチマークが取れるのですが、IEで実行すると「スクリプトタイムアウトの確認」のポップアップが表示されてしまうため、
以下の方法を使うなどして一時的に警告の確認画面が出ないようにしてあげる必要がありました。

余談: [HOWTO] スクリプトのタイムアウトを設定する方法

レジストリエディタ(Regedt32.exeなど)で、以下のキーを作って値をdword:ffffffffにするとスクリプトタイムアウトの確認ポップアップ表示を無効にすることができるようです。

[HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Styles]
"MaxScriptStatements"=dword:ffffffff
regedt32

このキーはデフォルトでは存在しません。キーが追加されていない場合、Internet Explorer 4.0 以降ではデフォルト値 5,000,000 がセットされている状態になります。なおこの値は Internet Explorer の内部処理で扱われる値であり、スクリプトのステートメント数とは異なります。

実行結果ですが、どれも微妙な差。スクリプトの実行エンジン自体は変わっていないようで、多量のGCが発生しないベンチマークではあまり差はでませんでした。

結論

今回試してみたベンチマークでは、数値として差はあまりでませんでしたが、

voxやLDRやGmailなどの実サービスでIE6を使った場合、
JavaScript実行途中に変に固まることがなくなって、

今までより体感速度が上がっているようでした。

ちなみに、自分が動作確認に使った環境は IE6 on WindowsXP SP2 / DELL Optiplex GX620 / Pentium4 3.40GHz / 1GB Memory です。

Operaでも非同期リクエストが並列処理できる img-JSONP

先日金床さんに教えてもらったOperaで非同期並列JSONPを実行させる方法を実際に試してみたら意外とすんなり動いてしまったので報告します。

最速インターフェース研究会 :: OperaでJSONPを非同期リクエストするより

JSONP が Opera だと非同期処理できない
http://d.hatena.ne.jp/secondlife/20060906/1157515075
に書かれているとおりOperaだとscript要素を足した瞬間にJavaScriptの実行が止まって、ロード完了まで後続のスクリプトが実行されなくなります。

サンプルコード

改善前(普通のJSONP)
Operaはスクリプトを追加するとタイマーが止まる(サンプルページ)
http://la.ma.la/misc/js/opera_jsonp_test.html
function test(){ 
        var s = document.createElement("script");
        var url = "http://del.icio.us/feeds/json/ma.la?";
        var now = new Date-0;
        url += "callback=c._"+now;
        c["_"+now]=function(obj){$("result").innerHTML=formatter(obj)};
        s.type = "text/javascript";
        s.charset = "utf-8";
        s.src = url;
        document.body.appendChild(s);
}
改善後(img + JSONP)
Opera img + JSONP(サンプルページ)
http://namazu.org/~takesako/opera/img_jsonp.html
function test(){ 
        var url = "http://del.icio.us/feeds/json/ma.la?";
        var now = new Date-0;
        url += "callback=c._"+now;
        c["_"+now]=function(obj){$("result").innerHTML=formatter(obj)};

        var img = document.createElement("img");
        img.onerror = function(e){
                var s = document.createElement("script");
                s.type = "text/javascript";
                s.charset = "utf-8";
                s.src = url;
                document.body.appendChild(s);
        };
        img.width = 0;
        img.height = 0;
        img.src = url;
        document.body.appendChild(img);
}

↑ ma.laさんのコードをそのままコピペしてここだけ修正しています。

■ 動作原理

IMGとして取得させキャッシュに入れる方法(金床さんのコメント)より:

JSONPのリソースを一度IMGタグから取得させてブラウザのキャッシュに入れておき、その後SCRIPTの要素として同じURLを再取得する、という方法が使えるかもしれません。

1.JSONPのリソースをIMGタグの追加などで取得する(このとき、あらかじめエラーハンドラを別の関数に設定しておく)
2.画像ではないのでエラーになる
3.エラーのイベントハンドラが呼び出されたらSCRIPTタグの追加で再度同じリソースを取得する
4.このときレスポンスは既にキャッシュに入っているため、一瞬で取得が終わる(限りなく非同期ぽい同期処理)

JSONPのレスポンスヘッダにPragma: no-cacheなどの指定があると動かない可能性が高いです。

非同期リクエストをimgタグで飛ばして、結果をonerrorハンドラで受けとって、ブラウザのキャッシュを再利用するという方法。

各ブラウザでの動作

HTTP Proxy を間に入れて、img + JSONP のHTTPリクエストを観測してみました。

続きを読む

Wiiリモコンの値をJavaScriptで取得する方法(Wiiインターネットチャンネル)

任天堂のQ&Aサイトで、Wiiリモコンの値を取得する方法が公開されていることを知人から教えてもらいました。


インターネットチャンネル向けのウェブページを作りたいのですが…。 : Q&A – Wii

インターネットチャンネルの拡張機能について知りたい
Wiiインターネットチャンネルでは特別な JavaScript を用いる事でWiiリモコンのひねりや
テレビとの距離、複数のコントローラの状態を取得する事ができます。

手元にWii本体の実機がないので(Wiiリモコンはある^^)まだ試していませんが、こんな感じでJavaScriptからWiiリモコンの値が取れるっぽいですね。

if (window.opera && window.opera.wiiremote) {
  var num = 0; // wiiremote number 0,1,2,3
  var pad = window.opera.wiiremote.update(num);
  if (pad.isEnabled && pad.isDataValid) {
    //
    var x = null;
    var y = null;
    if (pad.dpdValidity > 0) {
       x = pad.dpdX;
       y = pad.dpdY;
    }
    //
    // if (!pad.isBrowsing) { var hold = pad.hold; }
    var button_left  = (pad.hold & 1);
    var button_right = (pad.hold & 2);
    var button_up    = (pad.hold & 4);
    var button_down  = (pad.hold & 8);
    var button_plus  = (pad.hold & 16);
    var button_2     = (pad.hold & 256);
    var button_1     = (pad.hold & 512);
    var button_B     = (pad.hold & 1024);
    var button_A     = (pad.hold & 2048);
    var button_minus = (pad.hold & 4096);
    //
    var distance = pad.dpdDistance;
    var roll_angle = Math.atan2(pad.dpdRollY, pad.dpdRollX) * 180.0 / Math.PI;
    //
    // hogehoge
  }
}

numの値を変えれば、2本目以降のリモコンの値も取れるみたいです。

画面からの距離(dpdDistance)やリモコンの傾き(dpdRollY, dpdRollX)の情報が取れるのは面白いですね。
Wiiリモコンを用いたインタフェースの研究開発とかを個人の家庭用ゲーム機で実現できるので、hackしがいがあるかも。

拡張機能アツすぎます。

実際に動いたー!っていう人がいればぜひ教えてください。

JavaScriptでフォント名一覧を取得する3つの方法

先月今月と新しいメンバーが加わったサイボウズ・ラボですが、いま社内でfont-familyが密かなブームです。
ということで、ブラウザで使用できるフォント名一覧をJavaScriptで取得する方法について調べてみました。

 


■ 1. IE の Dialog Helper Object を利用してフォント名一覧を取得する

IE の Dialog Helper Object を利用して
フォント名の一覧を取得する方法がよく知られています。

まず、HTMLの中に以下のOBJECTタグを定義して、

<OBJECT id="dlgHelper" CLASSID="clsid:3050f819-98b5-11cf-bb82-00aa00bdce0b" width="0px" height="0px">
</OBJECT>

JavaScriptから以下のコードを実行すると、現在の環境で利用できるフォント名の一覧を取得することができます。

function getAllFontsByDialogHelper() { 
  var fontslist = '';
  try {
    for (var i = 1; i < dlgHelper.fonts.count; i++) {
      fontslist += dlgHelper.fonts(i) + '\n';
    }
  }
  catch(e) {
    fontslist = 'sorry, could not get fonts list.';
  }
  return fontslist;
}

非常にシンプルですが、動作するブラウザが Internet Explorer に激しく限定されてしまうのが難点です。

▼サンプル実行

※IE限定

参考リンク

動作デモ


■ 2. Flash の TextField.getFontList() を JavaScript から呼び出す

Flash には TextField.getFontList() というそのものズバリなメソッドがありますので、
TextField.getFontList() を実行する SWFファイルを作って、
フォント名一覧を取得する方法を考えてみます。

この方法は IE に限らず Flash Player のインストールされているブラウザで動作することが期待できますので、幅広いプラットフォームで実行可能な方法です。

奥さん情報によると、
これは英語圏では既に試されている方がいらっしゃるようでした。

▼汎用的なサンプル(3/14 16:00追記)

参考リンク

動作デモ


■ 3. LiveConnect を使って Javaアプレットの getAllFonts() を呼び出す

IE も使ってないし、Flash Player もインストールされていないブラウザで、フォント名一覧を取得したい場合はどうすればいいの?
ということで、LiveConnect を使う方法を実験してみました。

試してみたJavaScriptのコードは以下の通りです。

function getAllFontsByLiveConnect() {
  var fontslist = '';
  try {
    var fonts = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
    for (var i = 0; i < fonts.length; i++) {
      fontslist += fonts[i].getFontName() + '\n';
    }
  }
  catch(e) {
    fontslist = 'sorry, could not get fonts list.';
  }
  return fontslist;
}

LiveConnect は Javaアプレットの動作が有効になっている Netscape3以降, Firefox, Opera のブラウザで動作します。

Javaアプレットには、インスタンスを生成できない abstract メソッドとして
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts() がありますので、
これを呼び出すとjava.awt.Fontオブジェクトが配列で返ります。
これらのオブジェクトに対して Font.getFontName() を呼べばフォント名を取得できます。

▼サンプル実行

※IEでは動作しません

※Javaアプレットが1回起動するので、若干重たいです。

意外と知られていない LiveConnect ですが、
最初は Netspcape Navigator 3.0 の JavaScript 1.1 の頃からデフォルトで使えるようになっている機能で、
JavaScriptからJavaアプレットのオブジェクトを操作できるので(その逆も)、
使い方によっては面白いこともできそうです。
私もつい最近金床さんにLiveConnectの最新の活用事例を教えてもらいました。なんとjava.net.Socketクラスも利用できるそうです。これは便利!?

参考リンク

「WebベースのAJAX共同プログラミング開発環境」勉強会

一橋大学の長慎也先生をお招きしてAJAX勉強会を開催しました。

「WebベースのAJAX共同プログラミング開発環境」勉強会

日時:12/4(月) 第一部 16:00~  第二部 18:00~
場所:プルデンシャルタワー10F(サイボウズ・ラボ)
    http://labs.cybozu.co.jp/access.html

第一部(共同開発スタイル)

16:00 開場(ラボ見学自由時間)
16:30 Japanize について(奥一穂)
17:00 Plagger による共同開発の現在(竹迫良範)
17:15 SIPropアプリケーションサーバ(今村謙之)
17:40 休憩

第二部(プログラミング言語)

18:00 Ning の現状について(秋元裕樹)
18:30 aroe.jp(長慎也)
19:15 sn42.com(高橋さん・斉藤さん)
20:00 終了予定

各プロジェクトでは、
それぞれいろいろな方法でデータやプログラムのソースコードの共有の試みを行なっていて、
非常に参考になりました。

今回はオープンな募集は行ないませんでしたが、また機会があればこのような社外勉強会を開催したいと思います。

参加いただいた皆さん、ありがとうございました。

AJAJA – Yet Another Server Side JavaScript

Shibuya.js#2で言っていたAJAJA プロジェクトのページを公開しました。

AJAJA - Trac

当日の発表スライドも(若干修正して)あわせて公開しています。
Shibuya.js Technical Talk #2「Server Side JavaScript の歴史と未来」 (PPT)

AJAJA: Asynchronous JavaScript and JavaScript/ASP

AJAJA は「ブラウザだけでなくサーバサイドでも JavaScript を使おう!」というプロジェクトです

できること
– JavaScript を埋め込んだ ASP ファイルを処理する
– JavaScript から SQLite などのシステムライブラリを呼び出す
– JSAN のライブラリをサーバサイドで利用する
– Server Side JavaScript の実行処理系 asp_js を提供しています

asp_js の特徴
– IIS の ASP/JavaScirpt の記法をそのまま処理することができます
– Mozilla の C の JavaScript 処理系 SpiderMonkey を組み込んでいます
– SQLite を標準サポート、拡張も容易です

メインの開発者はOpenCOBOL/Gonzuiなどで有名な西田さん。ものすごく仕事が速いです。
奥さんや鶴岡さん達と一緒にいろいろアイディアを出し合ってプロジェクトを進めています。
まだまだできないことだらけですが、裏を返せば楽しいハックがまだ残っているということ。
共同開発者募集中ですので、興味のある方はぜひメーリングリストに参加してみてください。