2016-03-10 18 views
10

Próbuję zbudować gładką pętlę javascript przeglądarki animacji 60 klatek na sekundę. Zauważyłem, że garbage collector wciąga i dodaje zmienny niezerowy czas do klatek animacji. Zacząłem od śledzenia przydziałów w moim kodzie, a następnie odizolowałem pętlę od siebie. Używałem requestAnimationFrame i odkryłem, że w rzekomo "pustej" pętli nadal powoduje alokacje każdej iteracji i uruchamia garbage collector. Frustrująco to zdarza się również w innych mechanizmach zapętlenia.JavaScript jak stworzyć darmową pętlę animacji alokacji, aby uniknąć zbieracza śmieci?

Poniżej zamieściłem kilka jsfiddles i zrzuty ekranu demonstrujące przykładowe "puste pętle". Wszystkie próbki są z ~ 5 sekundowych linii czasu.

W tym momencie szukam najlepszego rozwiązania, które zminimalizuje odśmiecanie. Z poniższych przykładów wygląda na to, że requestAnimationFrame jest najgorszą opcją w tym względzie.

requestAnimationFrame

https://jsfiddle.net/kevzettler/e8stfjx9/

var frame = function(){ 
    window.requestAnimationFrame(frame); 
}; 

window.requestAnimationFrame(frame); 

enter image description here

setInterval

https://jsfiddle.net/kevzettler/p5LbL1am/

var frame = function(){ 
    //literally nothing 
}; 

window.setInterval(frame, 0); 

enter image description here

setTimeout

https://jsfiddle.net/kevzettler/9gcs6gqp/

var frame = function(){ 
    window.setTimeout(frame, 0); 
} 

window.setTimeout(frame, 0); 

enter image description here

+1

Czy próbowałeś podjąć sterty migawkę, aby sprawdzić ich rodzaju obiektów, które gromadzą? – Bergi

+0

@Bergi - jak to zrobić? –

+0

@JohnHaugeland https://developers.google.com/web/tools/chrome-devtools/memory-problems/heap-snapshots – Bergi

Odpowiedz

2

Nie jestem właściwie pewien, ale wydaje mi się, że pracownicy internetowych mają własne śmieciarze , a więc GC trafienie nie wpłynęłoby na FPS w głównym wątku (chociaż wpłynęłoby to nadal na możliwość wysyłania aktualizacji do głównego wątku)

+1

Jeśli głównym wątkiem jest po prostu wywołanie metody 'render' i nic więcej. Spowoduje to napotkanie problemów z alokacją podanych w powyższych przykładach. – kevzettler

+0

czekasz, czy mówisz, że samo 'rAF' * powoduje wywoływanie thrashu? –

+0

Tak, to właśnie pokazują przykłady. Jest to znany "błąd" chrome https://bugs.chromium.org/p/chromium/issues/detail?id=120186#c20 'rAF' przydziela obiekt' Number' przy każdym wywołaniu – kevzettler

1

Nie jestem ekspertem, ale z tego, co czytałem. Również natknąłem się na ten sam raport o błędzie, o którym wspomniałeś w swoich komentarzach:

Zgodnie z sugestią, przydzielenie obiektu Numer przy każdym połączeniu będzie zgodne z usuwaniem śmieci.

https://bugs.chromium.org/p/chromium/issues/detail?id=120186#c20

Sugeruje się również, że po prostu o debugger otwarty nagrywania śladów stosu może spowodować problemy. Zastanawiam się, czy to samo dotyczy zdalnego debugowania?

Ta odpowiedź sugeruje klapki flopping między klatkami animacji, aby zmniejszyć zbieranie śmieci: https://stackoverflow.com/a/23129638/141022

Sądząc po głębokości pytanie masz pytanie, jestem pewien, co mam zamiar powiedzieć jest oczywiste dla Ciebie , ale może być interesujące skoncentrowanie się na celu ogólnym (prawdopodobnie nie pomoże to w interesującej obserwacji Chrome).

Musimy pamiętać, że nie zamierzamy całkowicie pozbyć się zbierania śmieci, ponieważ jest to tak fundamentalne dla JS. Zamiast tego jesteśmy staramy się go maksymalnie zredukować, aby zmieścił się w renderowaniu naszych ramek z 16 ms (aby uzyskać 60 klatek na sekundę).

Jednym z podejść VelocityJs jest posiadanie jednego globalnego "haczyk", który obsługuje wszystkie animacje ...

Timers są tworzone podczas setInterval() setTimeout() i requestAnimationFrame() są używane. Występują dwa problemy z wydajnością: z tworzeniem timera: 1) zbyt duża liczba wyzwalaczy jednocześnie redukuje liczbę klatek ze względu na obciążenie przeglądarki związane z ich utrzymaniem, oraz 2) niewłaściwe oznaczenie czasu, w którym rozpoczyna się animacja, skutkuje zrzuceniem klatek w postaci .

Rozwiązaniem Velocity w pierwszym problemie jest utrzymywanie pojedynczej globalnej pętli znaczników , która cyklicznie przechwytuje wszystkie aktywne animacje Velocity na . Poszczególne timery nie są tworzone dla każdej animacji Velocity. W skrócie, Velocity priorytetuje planowanie przed przerwaniem.

http://www.sitepoint.com/incredibly-fast-ui-animation-using-velocity-js/

To wraz z ogólnymi zasadami na zmniejszenie zbierania śmieci, takie jak tworzenie pamięci podręcznej zawracania do ponownego użycia, a nawet obiekty przepisywanie metod, takich jak wycinek tablicy uniknąć śmieci.

https://www.scirra.com/blog/76/how-to-write-low-garbage-real-time-javascript

+0

żadna z tych informacji w żaden sposób nie odpowiada na pytanie. –

+1

Nie można zmniejszyć zbierania śmieci, które jest spowodowane przez rAF, ponieważ jest spowodowane przez rAF. Centralizacja kleszcza nie zmieni problemu, który powoduje kleszcz. Prędkość nie ma rozwiązania; ma problem. –

+1

Dzięki za opinie John, przypuszczam, że to, co próbowałem zilustrować, było tak, że rAF powoduje zbieranie śmieci. Jednak, podobnie jak w przypadku prędkości, można uzyskać bardzo wysokie wartości klatek na sekundę z problemem rAF, zamiast tego użyć innych sposobów, aby to zrekompensować. Flip flopowanie na przykład. Albo, jeśli pominąć problem dotyczący stacktrace, to prawdopodobnie po prostu debugowanie problemu powoduje więcej zbierania śmieci? –

Powiązane problemy