1. ホーム
  2. javascript

[解決済み] Javascriptの集合と配列のパフォーマンス

2022-08-09 10:36:58

質問

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.")