Уменьшить использование ресурсов этой JS программы? - PullRequest
0 голосов
/ 30 мая 2020

Я написал следующую программу JS, которую я запускаю из командной строки с помощью узла.

//step one: create an array of remaining creatures
var remainingCreatures = [];

//some config variables:
var amt = 1000; //amount of creatues generated
var maxhlt = 1000; //max value for creature health stat
var minhlt = 100; //min value for creature health stat
var maxatk = 100; //max value for creature attack stat
var minatk = 1; //min value for creature attack stat

function remove(target) { //helper function to easily remove creatues from the array
  var index = remainingCreatures.indexOf(target);
if (index > -1) {
  remainingCreatures.splice(index, 1);
}

}

//generate creatures
//each creature has an Attack, Health, and Aggressiveness , as well as Instabillity, the average of the three
//A creature's Instabillity is added to the attack points of its opponent in fights.
for (var i = 0; i < amt; i++) {
  var atkVal = Math.floor((Math.random() * maxatk) + minatk);
  var hltVal = Math.floor((Math.random() * maxhlt) + minhlt);
  var insVal = (atkVal + hltVal) / 2;

  remainingCreatures[i] = {num: i, atk: atkVal, hlt: hltVal, ins: insVal, fts: 0, ihlt: hltVal};
}
console.log(amt + " creatues generated, starting melee...");



function fight(cr1, cr2) { //function to handle fighting, randomly creates creature pairs and has them fight
  function attack(a, b) {
         console.log("[ROUND 1] Creature 1 (#" + a.num + ") is attacking first.");
    b.hlt = b.hlt - (a.atk + b.ins);
    console.log("[HIT] Creature #" + b.num + " health reduced to " + b.hlt);
    if (b.hlt <= 0) {
      console.log("[DEATH] Creature #" + b.num + " Eliminated");
      remove(b);
    } else {
      console.log("[ROUND 2] Creature 2 (#" + b.num + ") is attacking second.");
      a.hlt = a.hlt - (b.atk + a.ins);
      console.log("[HIT] Creature #" + a.num + " health reduced to " + a.hlt);
      if (a.hlt <= 0) {
      console.log("[DEATH] Creature #" + a.num + " Eliminated");
      remove(a);
    }
    }
  }
  console.log("[FIGHT] Pair generated: Creature #" + cr1.num + " and Creature #" + cr2.num);
  cr1.fts++;
  cr2.fts++;
   if (cr1.ins <= cr2.ins) {
    attack(cr1, cr2);
   } else {
    attack(cr2, cr1);
   }
}


for(;true;) {
  if(remainingCreatures.length == 1) break;
  fight(remainingCreatures[Math.floor(Math.random() * remainingCreatures.length)], remainingCreatures[Math.floor(Math.random() * remainingCreatures.length)]);
}

console.log(" ");
console.log("[WIN] Creature #" + remainingCreatures[0].num + " has won!");
console.log("Starting array size was " + amt + " creatures")
console.log(remainingCreatures[0]);

По какой-то причине это начинает замедляться и в конечном итоге задыхается, когда amt установлены действительно большие числа, например, один миллион. Для справки, это количество объектов, которые будут сгенерированы и добавлены в массив - как вы, вероятно, можете видеть в коде, этот массив часто зацикливается. Но даже с одним миллионом объектов размер каждого объекта составляет не более 80 байт. И вычисления, которые выполняет эта программа, очень просты. резко?

1 Ответ

0 голосов
/ 30 мая 2020

Во-первых, миллион чего угодно скажется на производительности, даже если она мала. Другая проблема заключается в том, что ваш дизайн изначально неэффективен.

Посмотрите на свою remove() функцию. Сначала он находит индекс элемента, а затем удаляет его. Если у вас в среднем один миллион элементов в этом массиве, ему нужно будет сравнить переданное значение с 500 000 элементов , чтобы найти его, прежде чем он сможет удалить. Есть один простой способ исправить это; передавать индексы напрямую, а не использовать .indexOf.

function fight(ind1, ind2) { //function to handle fighting, randomly creates creature pairs and has them fight
  var cr1 = remainingCreatures[ind1];
  var cr2 = remainingCreatures[ind2];
  function attack(a, b) {
         console.log("[ROUND 1] Creature 1 (#" + a.num + ") is attacking first.");
    b.hlt = b.hlt - (a.atk + b.ins);
    console.log("[HIT] Creature #" + b.num + " health reduced to " + b.hlt);
    if (b.hlt <= 0) {
      console.log("[DEATH] Creature #" + b.num + " Eliminated");
      remove(ind2);
    } else {
      console.log("[ROUND 2] Creature 2 (#" + b.num + ") is attacking second.");
      a.hlt = a.hlt - (b.atk + a.ins);
      console.log("[HIT] Creature #" + a.num + " health reduced to " + a.hlt);
      if (a.hlt <= 0) {
      console.log("[DEATH] Creature #" + a.num + " Eliminated");
      remove(ind1);
    }
    }
  }
  console.log("[FIGHT] Pair generated: Creature #" + cr1.num + " and Creature #" + cr2.num);
  cr1.fts++;
  cr2.fts++;
   if (cr1.ins <= cr2.ins) {
    attack(cr1, cr2);
   } else {
    attack(cr2, cr1);
   }
}


for(;true;) {
  if(remainingCreatures.length == 1) break;
  fight(Math.floor(Math.random() * remainingCreatures.length), Math.floor(Math.random() * remainingCreatures.length));
}

Существует не так много других способов легко улучшить производительность, но одного этого должно быть достаточно. Однако, чтобы сделать ваш код более читабельным, подумайте о замене этого:

for(;true;) {
  if(remainingCreatures.length == 1) break;
    fight(Math.floor(Math.random() * remainingCreatures.length), Math.floor(Math.random() * remainingCreatures.length));
}

на это:

// Consider using === and !== as best practice, but not necessary here
while (remainingCreatures.length != 1)
    fight(Math.floor(Math.random() * remainingCreatures.length), Math.floor(Math.random() * remainingCreatures.length));

( См. Эту ссылку для получения информации об этом комментарии. )

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...