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

问题描述 投票:2回答:1

我使用Cordova为iOS和Android编写了一个混合游戏。在某些Android设备上,几分钟后游戏崩溃,屏幕上出现一条消息“(App Name)已停止”。我一直试图找到过去一周崩溃的东西,但我一直无法找到它。我已经开始讨论这个问题,但是今天我发现了一些保证其自身线索的东西。请允许我先告诉你有关崩溃的事情,以及我为解决这个问题所做的工作。

游戏使用两个画布。一个不可见的,不属于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以某种方式触发垃圾收集?

javascript android cordova hybrid-mobile-app console.log
1个回答
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));
}

希望这会有所帮助。

请享用!

© www.soinside.com 2019 - 2024. All rights reserved.