Я знаю, что название не так уж объясняет, но вот история: я разрабатываю браузерную игру, в основном с использованием JavaScript и библиотеки Mapbox.
Все работает хорошо на настольных компьютерах, Android и iOS, но на iOS возникает одна проблема: после запуска игры в течение нескольких минут на телефоне внезапно появляются графические артефакты и отображается большая часть текста зашифрованным.
Вот несколько фотографий того, как выглядит телефон:
У меня вопрос : что именно в моем коде может вызвать это? Утечка памяти? ( ЛЭ : на самом деле это оказалось утечкой памяти)
Настоящий вопрос : как получается, что вы можете почти полностью заблокировать телефон, просто просматривая веб-страницу? Разве это не должно остановить Safari или хотя бы iOS?
Это не проблема для данного конкретного устройства, так как эта проблема может воспроизводиться на разных устройствах iPhone. (Я не уверен в разных версиях iOS).
Как воспроизвести ошибку:
- Откройте игру (внутри Safari).
- Дайте поработать 3-4 минуты.
- Проведите вниз по центру уведомлений, и все сойдет с ума.
Я добавил видео на YouTube, показывающее, как воспроизвести ошибку (на моем iPhone 5C).
Похоже, что проблема сначала появляется в центре уведомлений (если провести по меню сверху вниз).
На данный момент эта проблема, похоже, возникает только вiPhone 5C
iOS 9.2.1 (13D15). Это также происходит в новой версии iOS 9.3.
Чтобы решить эту проблему, мне нужно:
- Закройте приложение Safari (в котором открыта вкладка игры).
- Заблокируйте телефон. После разблокировки все возвращается в норму.
Некоторые подробности о самой игре :
- Игра показывает карту Mapbox и некоторые юниты над ней (маркеры).
- Сервер Node.js работает со скоростью 1 тик в секунду, и после каждого тика обновленное состояние игры отправляется в браузер через Socket.io.
- Каждый раз, когда браузер получает информацию о состоянии игры, он соответствующим образом обновляет маркеры.
- * Игра также может обновлять маркеры, если вы увеличиваете или уменьшаете масштаб или выбираете их.
EDIT2:
обнаружена утечка памяти (как и ожидалось). После исправления этой утечки (проверьте undefined
_icon) проблема больше не возникает. Это означает, что где-то в этих строках срабатывает ошибка Safari / iOS.
Вот как именно назывался каждый тик для каждого кластера (скрытого и сгруппированного с другими внутри MarkerCluster):
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
ДЕМО
Ура, мне удалось создать jsFiddle, который воспроизводит ошибку: https://jsfiddle.net/cte55cz7/14/ Откройте в Safari на iPhone 5C и подождите пару минут. На iPhone 6 и iPad mini происходит сбой страницы (как и ожидалось из-за утечки памяти)
Вот тот же код в HasteBin для всех, кто не хочет его запускать.
SuperUser
. Я надеюсь, что это подходящее место, чтобы задать этот вопрос.Ответы:
Эта утечка памяти, вероятно, связана с тем, как работает «JS Engine WebKit» [safari webkit-javascript llvm]
и действительно похоже на переполнение буфера виртуальной памяти, оказывающее прямое влияние на оставшуюся ОЗУ (совместно используемую и используемую также iOS для хранения графических элементов пользовательского интерфейса)
Относительно фрагмента кода: «[...] найти утечки памяти jQuery легко. Проверьте размер $ .cache. Если он слишком велик, проверьте его и посмотрите, какие записи остались и почему. [...]» ( http://javascript.info/tutorial/memory-leaks )
Позвольте мне ожидать, что это относительно этого цикла for :
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); }
Предполагая, что проверка выполнена, а также при условии, что вы нашли записи, вы можете очистить данные вручную с помощью removeData () или вы можете сначала использовать $ elem.detach (), а затем поместить $ (elem) .remove () в setTimeout.
источник