[ ] のほうが new Array(1000) より速いってホント？

# きっかけ

前回の記事を書くのために XSS の攻撃方法をいろいろ実験していたんだけど、同じ攻撃でもいろいろなスクリプトの挿入方法があることが分かったので、実行速度に差がないのか調べていたんですね。
それについては後日書くつもりなんですけど、JavaScript のパフォーマンスについてググっていたら、配列に 1000 個の要素を追加するときに [ ] で宣言する場合と、new Array(1000) で宣言する場合、[ ] のほうが V8 では２倍ほど速かったという記事を見つけてびっくりしました(ﾟдﾟ)

どういう実装にしたらそんなことが起こるんだろう？
C++ の std::vector だと、内部でバッファサイズが足りなくなると２倍の連続したメモリーを確保して、そちらへ丸ごとコピーする実装だったよね。
.NET Framework の List&lt;T&gt; クラスも同じような実装だったはず・・・。

```csharp:List<T>クラスから抜粋
private void EnsureCapacity(int min) {
    if (_items.Length < min) {
        int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;
        if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;
        if (newCapacity < min) newCapacity = min;
        Capacity = newCapacity;
    }
}
```

やっぱり２倍に拡張してるよね。
そしたらサイズが大きくなるに従って連続したメモリー確保とコピーコストは跳ね上がっていくから、最初からサイズを渡せるならその方がいいはず。
.NET のメモリー管理をちゃんと勉強してないけど、マネージだとメモリー連続してなくてもよかったりするのかな？

JavaScript だとメモリー連続してなくてもよさそうだから、１つのバッファが極端に大きくならないように一定程度大きくなると別のバッファを確保して連続しているように見せるのかなぁ・・・。
どういう実装なのか想像がつかないわ(´・ω・`)

# 実験してみた

というわけで、本当なのか実験してみました。

```js:テストコード
function test() {
	var run  = 100;
	var cnt  = 10000;
	var size = 10000000 / cnt;
	var msA  = 0;
	var msB  = 0;

	for (var i = 0; i < run; i++) {
		msA += testA(cnt, size);
		msB += testB(cnt, size);
	}
	console.log('A ' + (msA / run) + " ms");
	console.log('B ' + (msB / run) + " ms");

	function testA() {
		var startTime = new Date();
		for (var i = 0; i < cnt; i++) {
			var arr = [];
			for (var j = 0; j < size; j++) {
				arr[j] = 0;
			}
		}
		var endTime = new Date();
		return endTime - startTime;
	}

	function testB() {
		var startTime = new Date();
		for (var i = 0; i < cnt; i++) {
			var arr = new Array(size)
			for (var j = 0; j < size; j++) {
				arr[j] = 0;
			}
		}
		var endTime = new Date();
		return endTime - startTime;
	}
}
```

配列にゼロを１０００万回代入して、それに掛かる時間を計測します。
それを１００回実行した平均値を調べてみました。
`cnt` 変数の数字を大きくすると、小さな配列を何度も作って代入し、`cnt` 変数の数字を小さくすると、大きな配列を少ない回数作って代入するので、以下のような関係になります。
実行回数を合わせると時間掛かりすぎるので，こういう調べ方にしました(；´д｀)

|配列サイズ|10|100|1,000|10,000|100,000|1,000,000|
|---|---|---|---|---|---|---|---|
|実行回数|1,000,000|100,000|10,000|1,000|100|10|

# 計測結果

![[]-graph.png](https://qiita-image-store.s3.amazonaws.com/0/52104/9596b383-5122-19fd-1ada-685c1bb78b64.png)

![new-array-graph.png](https://qiita-image-store.s3.amazonaws.com/0/52104/42311c64-1152-9ca9-cb1f-438a13b7ad04.png)

基本的に new Array(x) のほうが速いですね。
V8 の処理の仕方がかわったのかな？
Chrome と Opera は傾向が完全に一致していて、誤差レベルだけど Opera のほうがちょっとだけ速い。
でも配列サイズが１０万になったとたんに、Chrome と Opera はパフォーマンスが極端に落ちていて、new Array(x) の方は IE と同レベルになっちゃいました。
よく使われるサイズで高速になるようにチューニングしたっぽいですね。

#### 配列 10 個の場合

||Internet<br>Explorer 11|Google<br>Chrome 37|Mozilla<br>Firefox 32|Opera 24|
|--:|:-:|:-:|:-:|:-:|
|[ ]|656.67|42.80|78.98|41.29|
|new Array(x)|737.88|22.69|126.77|21.36|

#### 配列 100 個の場合

||Internet<br>Explorer 11|Google<br>Chrome 37|Mozilla<br>Firefox 32|Opera 24|
|--:|:-:|:-:|:-:|:-:|
|[ ]|633.71|48.32|89.79|45.60|
|new Array(x)|576.24|14.10|35.15|12.97|

#### 配列 1,000 個の場合

||Internet<br>Explorer 11|Google<br>Chrome 37|Mozilla<br>Firefox 32|Opera 24|
|--:|:-:|:-:|:-:|:-:|
|[ ]|612.07|41.73|117.06|38.99|
|new Array(x)|559.40|10.64|54.06|9.82|

#### 配列 10,000 個の場合

||Internet<br>Explorer 11|Google<br>Chrome 37|Mozilla<br>Firefox 32|Opera 24|
|--:|:-:|:-:|:-:|:-:|
|[ ]|619.40|43.41|76.83|41.22|
|new Array(x)|558.55|10.39|80.28|9.88|

#### 配列 100,000 個の場合

||Internet<br>Explorer 11|Google<br>Chrome 37|Mozilla<br>Firefox 32|Opera 24|
|--:|:-:|:-:|:-:|:-:|
|[ ]|625.12|42.16|70.14|39.25|
|new Array(x)|559.32|411.66|55.29|375.22|

#### 配列 1,000,000 個の場合

||Internet<br>Explorer 11|Google<br>Chrome 37|Mozilla<br>Firefox 32|Opera 24|
|--:|:-:|:-:|:-:|:-:|
|[ ]|646.35|153.36|67.02|132.58|
|new Array(x)|598.95|807.45|66.91|782.40|

# 結論：お好きな方をどうぞ

どのブラウザでも配列のサイズが１００～１０００個のときが最速で、１０個まで小さいと微妙にパフォーマンスが落ちています。
[ ] のほうが速かったケースは １０個のときの IE と Firefox、１０万個以上のときの Chrome と Opera くらいかな。
配列を何度も作成する特殊なケースがあるなら、１００００個以下なら new Array(x) がよさそうで、それ以上の個数なら [ ] がいい。

でも普通に配列をいくつか作って使う程度なら、ぶっちゃけどっちでも変わらないから好きな方を使ったらいいんじゃないかなぁ。
可読性とか、タイプ数とか、検索性とか、コード規約とか、置かれた状況と ~~個人的な好み~~ で選択すればいいと思います (´∀`)