[解決済み] Javascriptの集合と配列のパフォーマンス
質問
SetsがJavascriptに比較的新しいからかもしれませんが、StackOでもどこでも、Javascriptの2つのパフォーマンスの違いについて述べた記事を見つけることができません。では、パフォーマンスの面で、この2つの違いは何でしょうか?具体的には、削除、追加、および反復に関してです。
どのように解決するのか?
OK、私は配列とセットの両方から要素を追加、反復、および削除することをテストしました。10 000 要素を使用する "small" テストと 100 000 要素を使用する "big" テストを実行しました。以下はその結果です。
コレクションに要素を追加する
と思われるかもしれませんが
.push
配列のメソッドは
.add
setメソッドよりも約4倍高速です。
コレクション内の要素の反復処理と変更
この部分のテストでは
for
ループを使って配列を繰り返し処理し
for of
ループで集合を反復処理します。ここでも、配列に対する反復処理の方が高速でした。今回は、quot;small" テストで 2 倍、quot;big" テストでほぼ 4 倍の時間がかかったため、指数関数的に速くなったように思われます。
コレクションから要素を削除する
さて、ここからが面白いところです。私は組み合わせで
for
ループと
.splice
を使用して配列からいくつかの要素を削除し、私は
for of
と
.delete
を使用して、セットからいくつかの要素を削除しました。しかし、quot;big" テストでは状況が一変し、配列からアイテムを削除するのに1955.1msかかり、セットからアイテムを削除するのに83.6msと23倍も速くなったのです。
結論
10k要素では、両方のテストは同等の時間 (配列: 16.6 ms、セット: 20.7 ms) を実行しましたが、100k要素を扱うときは、セットの方が明らかに勝っていました (配列: 1974.8 ms、セット: 83.6 ms) が、これは削除操作のためだけでした。それ以外は配列の方が速かったのです。その理由を正確に言うことはできませんでした。
私は、配列が作成され、入力され、次に、いくつかの要素が削除されるセットに変換され、セットが配列に再変換される、いくつかのハイブリッド シナリオで遊んでみました。この方法では、配列の要素を削除するよりもはるかに優れたパフォーマンスを得ることができますが、セットとの間の転送に必要な追加の処理時間は、セットではなく配列に値を入れることの利点を上回ります。結局、セットしか扱わない方が速いのです。それでも、重複のない大きなデータのデータ コレクションとして配列を使用することを選択した場合、1 つの操作で多くの要素を削除する必要がある場合、配列をセットに変換して削除操作を実行し、セットを配列に戻すことがパフォーマンス上有利になる可能性があるというのは興味深い考えです。
配列のコードです。
var timer = function(name) {
var start = new Date();
return {
stop: function() {
var end = new Date();
var time = end.getTime() - start.getTime();
console.log('Timer:', name, 'finished in', time, 'ms');
}
}
};
var getRandom = function(min, max) {
return Math.random() * (max - min) + min;
};
var lastNames = ['SMITH', 'JOHNSON', 'WILLIAMS', 'JONES', 'BROWN', 'DAVIS', 'MILLER', 'WILSON', 'MOORE', 'TAYLOR', 'ANDERSON', 'THOMAS'];
var genLastName = function() {
var index = Math.round(getRandom(0, lastNames.length - 1));
return lastNames[index];
};
var sex = ["Male", "Female"];
var genSex = function() {
var index = Math.round(getRandom(0, sex.length - 1));
return sex[index];
};
var Person = function() {
this.name = genLastName();
this.age = Math.round(getRandom(0, 100))
this.sex = "Male"
};
var genPersons = function() {
for (var i = 0; i < 100000; i++)
personArray.push(new Person());
};
var changeSex = function() {
for (var i = 0; i < personArray.length; i++) {
personArray[i].sex = genSex();
}
};
var deleteMale = function() {
for (var i = 0; i < personArray.length; i++) {
if (personArray[i].sex === "Male") {
personArray.splice(i, 1)
i--
}
}
};
var t = timer("Array");
var personArray = [];
genPersons();
changeSex();
deleteMale();
t.stop();
console.log("Done! There are " + personArray.length + " persons.")
コードを設定します。
var timer = function(name) {
var start = new Date();
return {
stop: function() {
var end = new Date();
var time = end.getTime() - start.getTime();
console.log('Timer:', name, 'finished in', time, 'ms');
}
}
};
var getRandom = function (min, max) {
return Math.random() * (max - min) + min;
};
var lastNames = ['SMITH','JOHNSON','WILLIAMS','JONES','BROWN','DAVIS','MILLER','WILSON','MOORE','TAYLOR','ANDERSON','THOMAS'];
var genLastName = function() {
var index = Math.round(getRandom(0, lastNames.length - 1));
return lastNames[index];
};
var sex = ["Male", "Female"];
var genSex = function() {
var index = Math.round(getRandom(0, sex.length - 1));
return sex[index];
};
var Person = function() {
this.name = genLastName();
this.age = Math.round(getRandom(0,100))
this.sex = "Male"
};
var genPersons = function() {
for (var i = 0; i < 100000; i++)
personSet.add(new Person());
};
var changeSex = function() {
for (var key of personSet) {
key.sex = genSex();
}
};
var deleteMale = function() {
for (var key of personSet) {
if (key.sex === "Male") {
personSet.delete(key)
}
}
};
var t = timer("Set");
var personSet = new Set();
genPersons();
changeSex();
deleteMale();
t.stop();
console.log("Done! There are " + personSet.size + " persons.")
関連
-
[解決済み] 配列から特定の項目を削除するにはどうすればよいですか?
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] JavaScript で配列に値が含まれているかどうかを確認するにはどうすればよいですか?
-
[解決済み] 配列に特定のインデックスで項目を挿入する方法 (JavaScript)
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み】オブジェクトからプロパティを削除する(JavaScript)
-
[解決済み] jqueryでdivの要素がオーバーフローしていないかチェックする
-
[解決済み] node.jsで文字列のsha1ハッシュを取得するにはどうすればよいですか?
-
[解決済み] 文字列がhtmlであるかどうかをチェックする
-
[解決済み] Node.jsのES6クラスをrequireで作る
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] JavaScript で範囲を作成する - 奇妙な構文
-
[解決済み] Chart.jsを使ってドーナツチャートの中にテキストを追加するには?
-
[解決済み] WebStormで未解決の変数が大量にある場合の警告に対処する方法は?
-
[解決済み] TypeScriptのdeclare classとinterfaceの違いとは?
-
[解決済み] 兄弟ノードを選択する方法はありますか?
-
[解決済み] javascriptで文字列から関数を作成する方法はありますか?
-
[解決済み] CORS: 認証モードは 'include' です。
-
[解決済み] JavaScript で `throw` の後に `return` をする必要がありますか?
-
[解決済み] V8 Javascript エンジンのスタンドアロン実行
-
[解決済み] リダイレクトされずにHTMLフォームを送信する方法