JavaScriptパフォーマンス改善(3) オブジェクトが配列かどうか判定する方法
JavaScriptパフォーマンス改善(3) オブジェクトが配列かどうか判定する方法
【調査対象】
- ブラウザ:
- IE,Firefox
- 比較対象JavaScriptコード:
- (e instanceof Array) vs (e.length > 1)
- 比較結果:
- (e instanceof Array)の方が数倍早かった。IEは約1.5倍,Firefoxは約5倍。
【Sample Code】
(Abbreviation) if (e instanceof Array) { // fast. IE 1.5 times. FF 5 times. } (Abbreviation) if (e.length > 1) { // slow } (Abbreviation)
JavaScriptパフォーマンス改善(2) document.getElementById()も遅い!
JavaScriptパフォーマンス改善(2) document.getElementById(要素ID)も、でら遅いじゃん!
【調査対象】
- ブラウザ:
- IE,Firefox
- 遅いJavaScriptコード:
- document.getElementById(id)
- 改善速度:
- IEは数百倍(200〜2000倍以上),Firefoxは8倍程度
- 改善方法:
- 最初にすべての要素をキャッシュしておき、キャッシュから要素を取得する。
【Sample Code】
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <meta http-equiv="Content-Script-Type" content="text/javascript" /> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Cache-Control" content="no-cache" /> <meta http-equiv="Expires" content="0" /> <title>JavaScript performance test</title> <script type="text/javascript"> // timer var TS = { _time: (new Date()).getTime(), _log: [], init: function() { TS._time = (new Date()).getTime(); }, record: function(in_title) { var nowTime = (new Date()).getTime(); var intervalTime = nowTime - TS._time; TS._log.push(in_title + " : " + intervalTime + "ms"); TS._time = (new Date()).getTime(); return intervalTime; }, getRecordList: function() { var result = TS._log; TS._log = []; return result; } } // element cache var FormElementCache = {}; // html initialize window.onload = function() { var formBody = document.getElementById("formBody"); var elementType = [ {tagName: "INPUT", type: "text"}, {tagName: "INPUT", type: "radio"}, {tagName: "INPUT", type: "checkbox"}, {tagName: "INPUT", type: "button"}, {tagName: "INPUT", type: "hidden"}, {tagName: "TEXTAREA", type: ""}, {tagName: "SELECT", type: ""} ]; for (var loop = 0; loop < 2000; loop++) { var type = loop % elementType.length; var e = document.createElement(elementType[type].tagName); if (elementType[type].type) { e.type = elementType[type].type; } e.id = "test" + loop; e.name = "test" + loop; e.value = 1 + loop; formBody.appendChild(e); } } // test program function performanceTest() { TS.init(); var ids = []; var felements = document.form1.elements; for (var fi = 0, lenfi = felements.length; fi < lenfi; fi++) { var e = felements[fi]; if (e.id) { FormElementCache[e.id] = e; ids.push(e.id); } } TS.record("form1.elements cached. count=" + ids.length); for (var loop=0; loop < 1; loop++) { for (var i = 0, len = ids.length; i < len; i++) { var e = document.getElementById(ids[i]); } } TS.record("document.getElementById[id] readed (" + loop + " loop)"); for (var loop=0; loop < 100; loop++) { for (var i = 0, len = ids.length; i < len; i++) { var e = FormElementCache[ids[i]]; } } TS.record("FormElementCache[id] readed (" + loop + " loop)"); alert(TS.getRecordList().join("\n")); } </script> </head> <body> <dl> <dt>JavaScript Performance Test</dt> <dd>document.getElementById(id) VS FormElementCache[id]</dd> </dl> <input type="button" value="Start!" onclick="performanceTest();" /><br /> <form name="form1"> <div id="formBody"></div> </form> </body> </html>
JavaScriptパフォーマンス改善(1) document.form1[]は遅い!
JavaScriptパフォーマンス改善(1) document.form1[要素名]は、でら遅い!
【調査対象】
- ブラウザ:
- IE,Firefox
- 遅いJavaScriptコード:
- document.form1[name] または document.form1.elements[name]
- 改善速度:
- IEは数百倍(300〜3000倍以上),Firefoxは10倍程度
- 改善方法:
- 最初にすべての要素をキャッシュしておき、キャッシュから要素を取得する。
【Sample Code】
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <meta http-equiv="Content-Script-Type" content="text/javascript" /> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Cache-Control" content="no-cache" /> <meta http-equiv="Expires" content="0" /> <title>JavaScript performance test</title> <script type="text/javascript"> // timer var TS = { _time: (new Date()).getTime(), _log: [], init: function() { TS._time = (new Date()).getTime(); }, record: function(in_title) { var nowTime = (new Date()).getTime(); var intervalTime = nowTime - TS._time; TS._log.push(in_title + " : " + intervalTime + "ms"); TS._time = (new Date()).getTime(); return intervalTime; }, getRecordList: function() { var result = TS._log; TS._log = []; return result; } } // element cache var FormElementCache = {}; // html initialize window.onload = function() { var formBody = document.getElementById("formBody"); var elementType = [ {tagName: "INPUT", type: "text"}, {tagName: "INPUT", type: "radio"}, {tagName: "INPUT", type: "checkbox"}, {tagName: "INPUT", type: "button"}, {tagName: "INPUT", type: "hidden"}, {tagName: "TEXTAREA", type: ""}, {tagName: "SELECT", type: ""} ]; for (var loop = 0; loop < 2000; loop++) { var type = loop % elementType.length; var e = document.createElement(elementType[type].tagName); if (elementType[type].type) { e.type = elementType[type].type; } e.id = "test" + loop; e.name = "test" + loop; e.value = 1 + loop; formBody.appendChild(e); } } // test program function performanceTest() { TS.init(); var names = []; var felements = document.form1.elements; for (var fi = 0, lenfi = felements.length; fi < lenfi; fi++) { var e = felements[fi]; var ename = e.name; if (ename) { if (FormElementCache[ename]) { if (FormElementCache[ename] instanceof Array) { FormElementCache[ename].push(e); } else { FormElementCache[ename] = [FormElementCache[ename], e]; } } else { FormElementCache[ename] = e; names.push(ename); } } } TS.record("form1.elements cached. count=" + names.length); var form1 = document.form1.elements; for (var loop=0; loop < 1; loop++) { for (var i = 0, len = names.length; i < len; i++) { var e = form1[names[i]]; } } TS.record("document.form1[name] readed (" + loop + " loop)"); for (var loop=0; loop < 100; loop++) { for (var i = 0, len = names.length; i < len; i++) { var e = FormElementCache[names[i]]; } } TS.record("FormElementCache[name] readed (" + loop + " loop)"); alert(TS.getRecordList().join("\n")); } </script> </head> <body> <dl> <dt>JavaScript Performance Test</dt> <dd>document.form1[name] VS FormElementCache[name]</dd> </dl> <input type="button" value="Start!" onclick="performanceTest();" /><br /> <form name="form1"> <div id="formBody"></div> </form> </body> </html>
IE7の記号が小さく表示される問題について
IE7(Internet Explorer7)にて一部の記号(○☐△×※など)が小さく表示されてしまう問題を調査した。
この問題が発生する条件を特定した。条件は以下のとおり。
条件1.ブラウザがInternet Explorer 7であること。
条件2.ホームページ(HTML)がUnicode(UTF-8)であること。
条件3.ホームページ(HTML)の中でフォントが指定されていないこと。
問題の原因は、IE7が多言語表示(Unicode)の際に記号の大きさを調整してしまうこと、らしい。(やれやれ)
よって、この問題を解消するには上記の逆を実施すればよい。
・ブラウザIE7でのアクセスを禁止する(現実的ではない)
・ホームページの文字コードをUnicode(UTF-8)以外のShift_JISなどにする。(国際化対応できなくなる)
・ホームページ内でフォントを指定する。(現実的なのはこれくらい。)
最近は国際化対応もあってUTF-8を使用することが多くなった。
また、WEBアプリケーションを組む上で、できるだけフォント指定は避けてきたものの、
今後は避けられなさそう。
だって、記号の○×が小さく表示されると、見た目が悪いせいか、必ずといっていいほど、
ユーザから指摘されてきたため。
この問題はそんなに難しい問題ではないと甘くみていたが、
ネット上を検索すること約1時間、なかなか有力な情報にたどりつけなかった。
とりあえず、解決したので、でめたしでめたし!
Trac Lightning1.6をインストールしてみた
Trac Lightning
http://sourceforge.jp/projects/traclight/wiki/FrontPage
インストール後、以下の作業を実施する。
apache22\binのlibapr-1.dllを複製してlibapr.dllを生成する。
これを実施しておかないと、apache22+svnへアクセスした際、プロセスが強制終了する。
なお、インストールすると、環境変数がいろいろと書き換わるので、注意が必要。
影響するアプリは以下のとおり。
・Apache2
・Subversion
・Python
・SQLite
これらのアプリケーションを運用しているマシンには影響がでるので、
Trac月をインストールしてはならない。
アンインストールしたとしても、環境変数が完全に元に戻るとは限らないので、注意が必要。
特に、Subversion(バージョン1.4)で文字化けを起こすようになってしまった場合、
環境変数にAPR_ICONV_PATHを追加する(元に戻す)ことで、文字化けを解消できる。