読者です 読者をやめる 読者になる 読者になる

htsign's blog

ノンジャンルで書くつもりだけど技術系が多いんじゃないかと思います

テキストをパースして要素に追加する処理比較

JavaScript DOM

有名なのはinnerHTMLですね。
ただ、これ以外にもテキストを評価してDOMツリーに追加する方法がありますので、今回はこれをやってみました。

単純にループで同じメソッドおよびプロパティ操作をしているだけです。
試行回数は1000回ですが、これはinnerHTMLの実行時間が長くなりすぎるからです。

まず計測用の関数を定義しておきます。
console.timeが使える場合はこれを使うようにし、使えない場合(IEさん)はDate()で時間を計測します。

var benchmark = function(callback){
	if (console.time && console.timeEnd){
		console.time("benchmark");
		callback();
		console.timeEnd("benchmark");
	}
	else {
		var time = new Date();
		callback();
		console.log("benchmark: ", new Date() - time);
	}
};


比較するのは次の4選手。
ご存じinnerHTMLに加えて、
insertAdjacentHTMLメソッド、
RangeオブジェクトのcreateContextualFragmentメソッド。
そしてDOMParserオブジェクトのparseFromStringメソッドです。

1) HTMLElement #innerHTML

benchmark(function(){
	Array.apply(null, Array(1000)).forEach(function(){
		document.body.innerHTML += "<div></div>";
	});
});

2) HTMLElement #insertAdjacentHTML

benchmark(function(){
	Array.apply(null, Array(1000)).forEach(function(){
		document.body.insertAdjacentHTML("beforeend", "<div></div>");
	});
});

3) Range #createContextualFragment

benchmark(function(){
	var range = document.createRange();
	range.selectNodeContents(document.body);
	Array.apply(null, Array(1000)).forEach(function(){
		document.body.appendChild(range.createContextualFragment("<div></div>"));
	});
});

4) DOMParser #parseFromString

benchmark(function(){
	var parser = new DOMParser();
	Array.apply(null, Array(1000)).forEach(function(){
		document.body.appendChild(
			parser.parseFromString("<div></div>", "application/xml").documentElement
		);
	});
});

結果

公平を期すため、ベンチ結果はabout:blank上で実行しました。

Internet Explorer 10 Mozilla Firefox 21 Google Chrome 26
innerHTML 3162ms (*) 619ms (*) 1238ms (*)
insertAdjacentHTML 49ms 13ms (*) 11ms
createContextualFragment 67ms 18ms (*) 9ms
parseFromString 78ms 83ms (*) 22ms

(*) ただし挿入対象のDOMツリーが巨大になればなるほど遅くなる

結論

  • Chromeは全体的に速い。流石Chrome先生。
  • Firefoxは基本的にDOMツリーがでかければでかいほど計算コストもでかくなる。
    普通の重量級ページで実行した場合、Firefoxが最も低速でした。
  • IEは可もなく不可もなく。
  • 何回も処理回す場合はinnerHTMLはなるべく避けるようにしましょう。
  • コード量と速度のバランスを考えるとinsertAdjacentHTMLがいいと思います。

っつーか

正直、別に今更やらなくてもベンチマーク取ってるサイトはググればいくらでも出てきますけどね…。