JavaScriptパフォーマンス改善(1) document.form1[]は遅い!

JavaScriptパフォーマンス改善(1) document.form1[要素名]は、でら遅い!

【調査対象】

ブラウザ:
IEFirefox
遅い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>