Запускает ли console.log () сборку мусора? - PullRequest
0 голосов
/ 30 августа 2018

Я написал гибридную игру с использованием Cordova для iOS и Android. На некоторых устройствах Android игра вылетает через несколько минут, и на экране появляется сообщение «(Имя приложения) остановлено». Я пытался найти то, что терпит крах это в течение прошлой недели, но я был не в состоянии найти это. Я начал тему об этом, но сегодня я заметил кое-что, что оправдывает свою собственную тему. Пожалуйста, позвольте мне сначала рассказать вам кое-что о сбое и о том, что я сделал, чтобы попытаться решить его.

В игре используются два холста. Тот, который не виден и который не является частью DOM (MAINCanvas) и который всегда имеет фиксированный размер независимо от истинных размеров экрана. Все рисование сделано на этом холсте. И другой холст, который имеет тот же размер, что и экран, и является видимым (DISPLAYCanvas). Я храню контекст для этих полотен в начале игры:

var MAINCanvas = document.createElement( "canvas" );
var DISPLAYCanvas = document.createElement( "canvas" );

document.body.appendChild(DISPLAYCanvas);

MAINCanvas.context = MAINCanvas.getContext("2d", { alpha: false } );
DISPLAYCanvas.context = DISPLAYCanvas.getContext("2d", { alpha: false } );

Основной цикл моей игры выглядит так:

function MainLoop() {
  doStuff();
  doSomeMoreStuff();
  Render(); // This renders all game elements on the invisible MAINCanvas

  DISPLAYCanvas.context.drawImage( MAINCanvas, 0, 0 );

  window.requestAnimationFrame( MainLoop );
}

Игра зависала каждый раз после нескольких минут игры. Чтобы выяснить, где он упал, я добавил несколько console.logs:

function MainLoop() {
  console.log( "Stuff" );
  doStuff();
  console.log( "SomeMoreStuff" );
  doSomeMoreStuff();
  console.log( "Render" );
  Render(); // This renders all game elements on the invisible MAINCanvas

  console.log( "Draw" );
  DISPLAYCanvas.context.drawImage( MAINCanvas, 0, 0 );     

  window.requestAnimationFrame( MainLoop );
}

Как оказалось, он разбился в разных местах.

Тогда я подозревал, что, возможно, это был виновник:

MAINCanvas.context = MAINCanvas.getContext("2d", { alpha: false } );
DISPLAYCanvas.context = DISPLAYCanvas.getContext("2d", { alpha: false } ); 

Я добавляю свойства к объекту DOM и помню, что где-то читал, что нет-нет, и это предотвращает (копирование) объекта от сборки мусора. Поэтому я изменил это следующим образом:

var MAINContext = MAINCanvas.getContext("2d", { alpha: false } );
var DISPLAYContext = DISPLAYCanvas.getContext("2d", { alpha: false }; 

И мой основной цикл:

function MainLoop() {
  console.log( "Stuff" );
  doStuff();
  console.log( "SomeMoreStuff" );
  doSomeMoreStuff();
  console.log( "Render" );
  Render(); // This renders all game elements on the invisible MAINCanvas

  console.log( "Draw" );
  DISPLAYContext.drawImage( MAINCanvas, 0, 0 );

  window.requestAnimationFrame( MainLoop );
}

И он больше не падал! Я был так счастлив, что наконец нашел то, что сломало это после 7 дней чистой расстраивающей отладки. Теперь я могу играть в эту игру без проблем.

Итак, чтобы подготовить игру к публикации, я удалил строки console.log (). Чтобы быть уверенным, я снова протестировал игру и ... она потерпела крах через несколько минут. Поэтому я добавил один файл console.log в свой mainloop:

function MainLoop() {
  console.log( "Stuff" );
  doStuff();
  doSomeMoreStuff();
  Render(); // This renders all game elements on the invisible MAINCanvas

  DISPLAYContext.drawImage( MAINCanvas, 0, 0 );

  window.requestAnimationFrame( MainLoop );
}

Протестировал снова, и он не вылетел. Удалил console.log () и он вылетел. Я пробовал несколько раз, и каждый раз, когда console.log () удаляется, игра вылетает. Если я добавлю это, это не так. Последовательно.

Единственное, о чем я могу думать сейчас, это то, что console.log каким-то образом запускает сборку мусора?

1 Ответ

0 голосов
/ 30 августа 2018

По моему мнению, это задержка, которую console.log () создает в жизненном цикле.

В прошлом были подобные проблемы.

Попробуйте обернуть код в тайм-аут с задержкой 0 секунд для многопоточного выполнения этого цикла.

Пример

function MainLoop() {
  //console.log("MainLoop start");
  doStuff();
  doSomeMoreStuff();
  Render(); // This renders all game elements on the invisible MAINCanvas

  DISPLAYContext.drawImage( MAINCanvas, 0, 0 );

  window.setTimeout(function(){
      window.requestAnimationFrame( MainLoop );
  },0);
}

Возможно, поиграйте с ним и добавьте другие интенсивные действия таким же образом.

EDIT: Вы также можете попытаться уменьшить частоту кадров - возможно, этим специальным устройствам Android не хватает мощности для обработки частоты кадров ...

* ** 1 022 тысяча двадцать-один * Пример
var framesPerSecond = 10;

function MainLoop() {
  //console.log("MainLoop start");
  doStuff();
  doSomeMoreStuff();
  Render(); // This renders all game elements on the invisible MAINCanvas

  DISPLAYContext.drawImage( MAINCanvas, 0, 0 );

  window.setTimeout(function(){
      window.requestAnimationFrame( MainLoop );
  }, (1000 / framesPerSecond));
}

Надеюсь, это как-то поможет.

НАСЛАЖДАЙТЕСЬ!

...