性能テスト用DOM生成 jQuery プラグインを作ってみた

DOMアクセスの性能計測の際に利用するために、テスト用DOM生成の jQuery プラグインを作ってみた。

jquery.appendchildren.js

;(function($) {
	var _ID_DLMT = '_';
	var _ID_NUM_DLMT = '';

	var _nodeStructureMap = {
		  div:   ['div']
		, table: ['table', 'tbody', 'tr', 'td']
		, ul:    ['ul', 'li']
		, ol:    ['ol', 'li']
	};

	function _createCurrentIdNum(parentIdNum, width) {
		return parentIdNum + _ID_NUM_DLMT + width;
	}

	function _createId(idSeed, nodeName, width, parentIdNum) {
		return idSeed + _ID_DLMT + _createCurrentIdNum(parentIdNum, width) + _ID_DLMT + nodeName;
	}
	
	function _createIdByArray(idSeed, nodeName, positionArray) {
		return _createId(idSeed, nodeName, positionArray.pop(), positionArray.join(_ID_NUM_DLMT));
	}

	function _createBegin(idSeed, nowWidth, parentIdNum, nodeStructure) {
		var begin = '';
		for(var i = 0, nslen = nodeStructure.length; i < nslen; i++) {
			var nodeName = nodeStructure[i];
			begin += '<' + nodeName + ' id="' + _createId(idSeed, nodeName, nowWidth, parentIdNum) + '">';
		}
		return begin;
	}

	function _createEnd(nodeStructure) {
		var end = '';
		for(var i = nodeStructure.length - 1; i >= 0; i--) {
			var nodeName = nodeStructure[i];
			end += '</' + nodeName + '>';
		}
		return end;
	}

	function _createChild(nowWidth, nowDepth, options, idSeed, parentIdNum, nodeStructure) {
		var begin = _createBegin(idSeed, nowWidth, parentIdNum, nodeStructure);
		var end = _createEnd(nodeStructure);
		return begin + _createChildren(nowDepth+1, options, idSeed, _createCurrentIdNum(parentIdNum, nowWidth), nodeStructure) + end;
	}

	function _createChildren(nowDepth, options, idSeed, parentIdNum, nodeStructure) {
		if(nowDepth >= options.depth) {
			return options.leafInnerHTML;
		}
		else {
			var children = '';
			for(var nowWidth = 0, width = options.width; nowWidth < width; nowWidth++) {
				children += _createChild(nowWidth, nowDepth, options, idSeed, parentIdNum, nodeStructure);
			}
			return children;
		}
	}

	function _getIdSeed(elem, options) {
		if (options.idSeed || elem === 0) {
			return options.idSeed;
		}
		else if(elem.id || elem === 0) {
			return elem.id;
		}
		else {
			return new Date().getTime();
		}
	}

	$.fn.appendChildren = function(options) {
		var options = $.extend($.fn.appendChildren.defaults, options);
		this.each( function() {
			var idSeed = _getIdSeed(this, options);
			var nodeStructure = _nodeStructureMap[options.nodeName];
			if(nodeStructure) {
				$(this).append($(_createChildren(0, options, idSeed, '', nodeStructure)));
			}
		});
		return this;
	};

	$.fn.appendChildren.defaults = {
		  idSeed:        undefined
		, nodeName:      'div'
		, leafInnerHTML: ''
		, depth:         1
		, width:         1
	};

	$.appendChildren = {
		getId: function(idSeed, nodeName, positionArray) {
			return _createIdByArray(idSeed, nodeName, positionArray);
		}
	};
})(jQuery);

使用例1〜いろんな要素を作ってみる〜

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
  <HEAD>
    <TITLE>テスト用DOM生成機能の性能</TITLE>
      <SCRIPT src="http://code.jquery.com/jquery-1.6.2.js"></SCRIPT>
      <SCRIPT src="./aop.js"></SCRIPT>
      <SCRIPT src="./jquery.appendchildren.js"></SCRIPT>
      <SCRIPT src="./okkn.js"></SCRIPT>
      <SCRIPT type="text/javascript">
        //<![CDATA[
          $(function(){
              var st = okkn.util.createSpeedTester();

              // テスト用DOM生成のパフォーマンス計測のために、計測処理を織り込む
              $.aop.around( {target: $, method: 'appendChildren'}, 
                  function(invocation) {
                      var stName = invocation.method + '_' + JSON.stringify(invocation.arguments[0]) + '_' + (new Date().getTime());
                      st.setStart(stName);
                      invocation.proceed(invocation.arguments);
                      st.setEnd(stName);
                  }
              );

              $('#target').appendChildren();
              $('#target').appendChildren({nodeName:'table', leafInnerHTML:'葉', depth:5, width:3});
              $('#target').appendChildren({idSeed:'ol1', nodeName:'ol', leafInnerHTML:'葉', depth:5, width:3});
              $('#target').appendChildren({idSeed:'ul1', nodeName:'ul', leafInnerHTML:'葉', depth:5, width:3});
              $('#target').appendChildren({idSeed:'div1', nodeName:'div', leafInnerHTML:'葉', depth:5, width:3});

              st.outputAllResults();
          });
        //]]>
      </SCRIPT>
  </HEAD>
  <BODY>
    <DIV id="target">
  </BODY>
</HTML>

使用例2〜末尾要素アクセスの性能測定〜

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
  <HEAD>
    <TITLE>テスト用DOM生成 性能計測</TITLE>
      <SCRIPT src="http://code.jquery.com/jquery-1.6.2.js"></SCRIPT>
      <SCRIPT src="./jquery.appendchildren.js"></SCRIPT>
      <SCRIPT src="./okkn.js"></SCRIPT>
      <SCRIPT type="text/javascript">
        //<![CDATA[
          $(function(){
              var isChanged = true;

              $('#nodeName, #depth, #width').change(function(){
                  isChanged = true;
              });
              
              $('#btnExec').click(function(){
                  var options = {nodeName:$('#nodeName').val(), depth:$('#depth').val(), width:$('#width').val()};
                  if(isChanged) {
                      $('#target').empty();
                      $('#target').appendChildren(options);
                      isChanged = false;
                  }

                  var positionArray = [];
                  for(var i = 0; i < options.depth; i++) {
                      positionArray.push(options.width-1);
                  }
                  var editTargetId = $.appendChildren.getId('target', $('#selectNodeName').val(), positionArray);

                  var st = okkn.util.createSpeedTester();
                  var count = $('#count').val();
                  var stName = JSON.stringify(options) + count + '回';
                  st.setStart(stName);
                  for(var i = count; i ; i--) {
                      var editTarget = $('#'+editTargetId);
                      var text = editTarget.text();
                      editTarget.text(text+'a');
                  }
                  st.setEnd(stName);

                  st.outputResult(stName);
              });
          });
        //]]>
      </SCRIPT>
  </HEAD>
  <BODY>
    <TABLE>
      <TR>
        <TD><LABEL for="nodeName">生成ノード名称:</LABEL></TD>
        <TD><INPUT type="text" id="nodeName" value="table"></INPUT></TD>
        <TD><LABEL for="depth">深さ:</LABEL></TD>
        <TD><INPUT type="text" id="depth" value="5"></INPUT></TD>
        <TD><LABEL for="width">幅:</LABEL></TD>
        <TD><INPUT type="text" id="width" value="5"></INPUT></TD>
      </TR>
      <TR>
        <TD><LABEL for="selectNodeName">アクセスノード名称:</LABEL></TD>
        <TD><INPUT type="text" id="selectNodeName" value="td"></INPUT></TD>
        <TD><LABEL for="count">実行回数:</LABEL></TD>
        <TD><INPUT type="text" id="count" value="1000"></INPUT></TD>
      </TR>
      <TR>
        <TD><INPUT type="button" id="btnExec" value="実行"></INPUT></TD>
      </TR>
    </TABLE>
    <DIV id="target"></DIV>
  </BODY>
</HTML>