Wiem, że tytuł nie jest zbyt objaśniający, ale oto historia: tworzę grę przeglądarkową, głównie przy użyciu JavaScript i biblioteki Mapbox.
Wszystko działa dobrze na desktopie, Androidzie i iOS, ale jeden problem pojawia się na iOS: po kilku minutach uruchomienia gry telefon nagle zaczyna mieć artefakty graficzne i wyświetla większość zaszyfrowanego tekstu.
Oto kilka zdjęć, jak zaczyna wyglądać telefon:
Moje pytanie brzmi: co dokładnie w moim kodzie może to spowodować? Wyciek pamięci? ( LE : okazało się, że to wyciek pamięci)
. Prawdziwe pytanie brzmi: jak to się dzieje, że można prawie zepsuć cały telefon, po prostu przeglądając stronę internetową? Czy Safari nie powinno tego zatrzymać, a przynajmniej iOS?
Nie stanowi to problemu w przypadku tego konkretnego urządzenia, ponieważ ten problem można odtworzyć na różnych urządzeniach iPhone. (Nie jestem pewien co do różnych wersji iOS).
Jak mogę odtworzyć błąd:
- Otwórz grę (w Safari).
- Pozwól mu działać przez 3-4 minuty.
- Przesuń w dół centrum powiadomień i wszystko zwariuje.
Dodałem film z YouTube pokazujący, jak mogę odtworzyć błąd (na moim iPhonie 5C).
Wygląda na to, że problem najpierw pojawia się w centrum powiadomień (jeśli przesuniesz menu od góry w dół).
Na razie ten problem wydaje się występować tylko wiPhone 5C
systemie iOS 9.2.1 (13D15). Występuje również w nowej wersji iOS 9.3.
Aby rozwiązać ten problem, muszę:
- Zamknij aplikację Safari (w której karta gry jest otwarta).
- Zablokuj telefon. Po odblokowaniu wszystko wraca do normy.
Kilka szczegółów na temat samej gry :
- Gra pokazuje mapę Mapbox i kilka jednostek nad nią (znaczniki).
- Serwer Node.js działa z szybkością 1 taktu na sekundę, a po każdym taktowaniu zaktualizowany stan gry jest wysyłany do przeglądarki za pośrednictwem Socket.io.
- Za każdym razem, gdy przeglądarka otrzymuje stan gry, odpowiednio aktualizuje znaczniki.
- * Gra może również aktualizować znaczniki, jeśli powiększysz lub pomniejszysz lub jeśli je wybierzesz.
EDIT2:
Znaleziono wyciek pamięci (zgodnie z oczekiwaniami). Po naprawieniu tego wycieku (sprawdź, czy nie ma undefined
_icon) problem już nie występuje. Oznacza to, że gdzieś w tych liniach pojawia się błąd Safari / iOS.
Oto, co dokładnie nazywano każdym tikiem dla każdej jednostki, która została zgrupowana (została ukryta i zgrupowana z innymi w 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);
A to jest icons
tablica:
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
połączenie pochodzi z tej biblioteki: https://github.com/kottenator/jquery-circle-progress
PRÓBNY
Tak, udało mi się stworzyć jsFiddle, które odtwarza błąd: https://jsfiddle.net/cte55cz7/14/ Otwórz w Safari na iPhonie 5C i poczekaj kilka minut. Na iPhonie 6 i iPadzie mini strona ulega awarii (zgodnie z oczekiwaniami z powodu wycieku pamięci)
Oto ten sam kod w HasteBin dla każdego, kto nie chce go uruchamiać.
SuperUser
. Mam nadzieję, że uznano to za właściwe miejsce do zadawania tego pytania.Odpowiedzi:
Ten wyciek pamięci jest prawdopodobnie spowodowany działaniem „silnika JS WebKit” [safari webkit-javascript llvm]
i naprawdę wygląda na przepełnienie bufora pamięci wirtualnej, mające bezpośredni wpływ na pozostałą pamięć RAM (współdzieloną i używaną również przez iOS do przechowywania elementów graficznych interfejsu użytkownika)
W odniesieniu do fragmentu kodu: „[...] znajdowanie wycieków pamięci jQuery jest łatwe. Sprawdź rozmiar $ .cache. Jeśli jest za duży, sprawdź go i zobacz, które wpisy pozostają i dlaczego. [...]” ( http://javascript.info/tutorial/memory-leaks )
Spodziewam się, że jest to relatywne do tej pętli 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); }
Zakładając, że inspekcja jest zakończona, a także zakładając, że znajdziesz wpisy, możesz chcieć wyczyścić dane ręcznie za pomocą removeData () lub możesz najpierw użyć $ elem.detach (), a następnie wstawić $ (elem) .remove () w setTimeout.
źródło