我知道 Headers 不是那么解释,但这是故事:我正在开发一个浏览器游戏,主要使用JavaScript和Mapbox库 .
在桌面,Android和iOS上一切都运行良好但在iOS上出现一个问题:在让游戏运行几分钟之后,手机突然开始出现图形伪影并显示大部分文本乱码 .
以下是一些手机开始时的照片:
My question 是:我的代码到底能引起什么?内存泄漏? ( LE :事实证明它实际上是内存泄漏)
The real question 是:你怎么能通过浏览网页几乎把整个手机搞得一团糟? Safari不应该停止这个,或者至少是iOS吗?
这不是这个特定设备的问题,因为这个问题可以在不同的iPhone设备上重现 . (我对不同的iOS版本不太确定) .
我怎么能 reproduce 错误:
-
打开游戏(在Safari中) .
-
让它运行3-4分钟 .
-
向下滑动通知中心,一切都变得疯狂 .
我添加了一个YouTube video,显示我如何重现错误(在我的iPhone 5C上) .
似乎问题首先出现在通知中心(如果您从顶部向下滑动菜单) .
至于现在,这个问题似乎只发生在iOS 9.2.1(13D15)的iPhone 5C
上 . 它也出现在新的iOS 9.3版本上 .
为了 fix 这个问题,我必须:
-
关闭Safari应用程序(游戏选项卡打开) .
-
锁定手机 . 解锁后一切恢复正常 .
关于 game 本身的一些细节:
-
游戏显示一个Mapbox Map 和一些单位(标记) .
-
Node.js服务器以1滴/秒的速度运行,每次滴答后,更新的游戏状态通过Socket.io发送到浏览器 .
-
每次浏览器收到游戏状态时,它都会相应地更新标记 .
-
*如果您放大或缩小或者选择它们,游戏也可能会更新标记 .
EDIT2: 发现内存泄漏(如预期的那样) . 修复此泄漏(检查 undefined
_icon)后,问题不再发生 . 这意味着,在这些行的某处,触发了Safari / iOS错误 .
对于每个聚类的单元(隐藏在MarkerCluster中并与其他单元组合在一起),以下是每个tick的确切调用内容:
var $icon = $(marker._icon); // marker._icon is undefined because of the clustering
$icon.html('');
$icon.append($('<img class="markerIcon" src="' + options.iconUrl + '" />'));
var iconX = 10;
var iconY = -10;
var iconOffset = 0;
for(var v in this.icons) {
this.icons[v].css('z-index', + $icon.css('z-index') + 1);
this.icons[v].css('transform', 'translate3d(' + iconX + 'px,'
+ (iconY + iconOffset) + 'px,' + '0px)');
iconOffset += 20;
this.icons[v].appendTo($icon);
}
// Fire rate icons
this.attackRateCircle = $('<div class="circle"></div>');
this.attackRateCircle.circleProgress({
value: 0,
size: 16,
fill: { color: "#b5deff" },
emptyFill: 'rgba(0, 0, 0, 0.5)',
startAngle: -Math.PI / 2,
thickness: 4,
animation: false,
});
this.attackRateCircle.hide();
// Create and display the healthbar
this.healthBar = $('<div>').addClass('healthBar ');
this.healthBar.css('z-index', $icon.css('z-index'));
this.healthBarFill = $('<span class="fill">');
this.healthBar.append(this.healthBarFill);
$icon.append(this.healthBar);
$icon.append(this.attackRateCircle);
这是 icons
数组:
this.icons = {
attack_order: $('<img src="img/attack.png" class="status_icon">'),
attack: $('<img src="img/damage.png" class="status_icon icon_damage">'),
hit: $('<img src="img/hit.png" class="status_icon icon_hit">'),
};
circleProgress
来自此库的电话:https://github.com/kottenator/jquery-circle-progress
DEMO
是的,我已经能够创建一个重现错误的jsFiddle:https://jsfiddle.net/cte55cz7/14/在iPhone 5C上的Safari上打开并等待几分钟 . 在iPhone 6和iPad mini上页面崩溃(正如预期的那样由于内存泄漏)
Here's the same code in a HasteBin, for anyone who doesn't want to run it.
1 回答
这个内存泄漏可能是由于'WebKit的JS引擎'如何工作[safari webkit-javascript llvm]
并且看起来像是一个虚拟内存缓冲区溢出,对剩余的RAM有直接影响(iOS共享和使用它来存储用户界面图形元素)
相对于这段代码:"[...]finding jQuery memory leaks is easy. Check the size of $.cache. If it’s too large, inspect it and see which entries stay and why. [...]"(http://javascript.info/tutorial/memory-leaks)
让我期待它与 for loop 相关:
假设检查已完成,并且假设您找到了条目,则可能需要使用 removeData() 手动清理数据,或者您可以先使用 $elem.detach() 然后将 $(elem).remove() 放入setTimeout .