console.log()是否触发垃圾收集?

时间:2018-08-30 12:33:32

标签: javascript android cordova hybrid-mobile-app console.log

我使用iOS和Android的Cordova编写了一款混合游戏。在某些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()行。可以肯定的是,我再次测试了游戏,...在几分钟后崩溃了。因此,我在mainloop中添加了一个console.log:

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 :(得分:0)

我认为这是 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);
}

也许可以尝试一下,并以相同的方式添加其他密集动作。

编辑: 您还可以尝试降低帧速率-也许这些特殊的Android设备没有足够的功能来处理帧速率...

示例

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));
}

希望这会有所帮助。

享受!