Częste błędy JavaScript, które poważnie wpływają na wydajność? [Zamknięte]

10

Na niedawnym spotkaniu UI / UX, w którym uczestniczyłem, przekazałem informacje zwrotne na stronie internetowej, która używała Javascript (jQuery) do interakcji i interfejsu użytkownika - były to dość proste animacje i manipulacje, ale wydajność na przyzwoitym komputerze była przerażająca.

Przypomniało mi to wiele stron / programów, które widziałem z tym samym problemem, w których pewne działania po prostu absolutnie niszczą wydajność. Jest to głównie w (lub co najmniej bardziej zauważalne) sytuacjach, w których JavaScript prawie zastępuje Flash. Jest to wyraźny kontrast z niektórymi aplikacjami internetowymi, których używałem, które mają znacznie więcej Javascript i funkcjonalność, ale działają bardzo płynnie (COGNOS firmy IBM to taki, który mogę sobie wyobrazić z góry).

Chciałbym poznać niektóre z typowych problemów, które nie są brane pod uwagę przy opracowywaniu JS, które zabijają wydajność witryny.

Nic
źródło
Prawdopodobnie to samo, co w przypadku każdego innego programu: Wykonywanie więcej pracy niż to konieczne i wykonywanie tej samej pracy w kółko, często setki razy.
1
@ delnan to prawda, ale wygląda na to, że w JS jest znacznie bardziej rozpowszechniona. Może postrzeganie?
Nic.
1
Mówiąc o JavaScripcie, mówienie o „witrynie” jest dość zwyczajne. Jest wszędzie i jest używany do wszystkiego we współczesnych czasach.
Adam Crossland
@Adam Crossland masz całkowitą rację - myślę, że w tym samym przypadku pomogłem programistom z natywną aplikacją, która również w dużym stopniu polegała na jQuery.
Nic.
1
Nie jest to dokładnie odpowiedź na twoje pytanie, więc robię z tego komentarz: napotkałem sytuacje, w których JavaScript generowało dużo renderowania, a tak naprawdę silnik renderowania przeglądarki zużył sekundy. Dlatego, aby poradzić sobie z wąskim gardłem wydajności, najpierw szukałbym niepotrzebnych operacji renderowania.
user281377,

Odpowiedzi:

8

Typowy zabójca wydajności wywołuje .lengthfunkcję HTMLCollection w forpętli:

function foo(collection) {
    for (var index = 0; index < collection.length; index++) {
        // do something awesome here
    }
}

Ten anty-wzór powoduje, że wielkość kolekcji jest obliczana przy każdym przejściu przez pętlę. Lepszym rozwiązaniem jest obliczenie długości poza pętlą:

function foo(collection) {
    var collectionLen = collection.length;
    for (var index = 0; index < collectionLen; index++) {
        // do something awesome here
    }
}
Adam Crossland
źródło
3
Zależy od przeglądarki. Weź ten wzorzec jako przykład: w FF 5, „normalne” One działa w prawie tym samym czasie co „zoptymalizowane” wersji. I nawet w naprawdę starych i powolnych przeglądarkach, coś takiego prawdopodobnie nie będzie wąskim gardłem, jeśli JS rzeczywiście zrobi coś interesującego z elementami.
1
Hmm! Być może dzisiejsze wysoce optymalizujące kompilatory JIT sprawiają, że ta odrobina mądrości staje się przestarzała.
Adam Crossland
4
Nie jestem tutaj prawdziwym ekspertem, ale ze specyfikacji ECMA wynika, że ​​długość jest tylko właściwością obiektu tablicy. Tak więc wywołanie go zwraca wartość zamiast zliczać wszystkie elementy. Nie mam pojęcia, czy wszystkie implementacje są zgodne ze specyfikacją, ale jeśli tak, kod w ogóle nie poprawia wydajności.
Jacek Prucia
4
@JacekPrucia Powiedział, że kolekcja , a nie tablica - zwykle w prawdziwym kodzie oznacza to listę elementów DOM zwróconych przez funkcje takie jak document.getElementsByTagName. Funkcja zwraca aktywność, nodeListktóra ponownie oblicza jej długość za każdym razem, gdy .lengthuzyskuje się dostęp do właściwości.
Yi Jiang
2
Test porównawczy @JacekPrucia to poprawa wydajności. Wyszukiwanie nieruchomości nie jest tanie.
Raynos
4

Nie, problem nie pochodzi od JS używanego jako zamiennik pamięci flash. Jeśli nie jesteś do tego przekonany, udokumentuj informacje o skryptach akcji: jest bardzo zbliżony do JS.

Jako zabójca występów możesz znaleźć kilka złych praktyk:

  • Dołącz moduł obsługi zdarzeń do zdarzeń ciągłych, takich jak przewijanie, poruszanie myszką lub podobne rzeczy. Ma to dwie wady: jeśli zdarzenie nie zostanie wystarczająco uruchomione, aplikacja nie będzie reaktywna. Jeśli uruchomi się za bardzo, będziesz mieć ogromne obciążenie procesora za darmo.
  • Wykonywanie synchronicznych wywołań AJAX. JavaScript nie jest wielowątkowy, więc gdy część JS na coś czeka, aplikacja zostaje zawieszona. Lepiej użyj asynchronicznych wywołań AJAX i w ten sam sposób użyj setTimeout / setInterval, aby podzielić długą fazę obliczeń i zachować aktywność aplikacji.
  • Wysoka złożoność algorytmu jak w innych językach.
deadalnix
źródło
Widziałem więcej niż kilka aplikacji, które próbują obracać, ułatwiać lub animować obrazy w pełnej przeglądarce i nie udaje im się to w tym procesie - stąd pochodzi komentarz dotyczący wymiany Flasha :)
Nic
Ponieważ pierwszy A w AJAX oznacza asynchroniczny, technicznie nie jest to AJAX, jeśli jest synchroniczny, ale twój punkt jest nadal dobry.
Karl Bielefeldt,
Tak, prawda, to nie jest wyłącznie AJAX. Ale i tak należy tego unikać: D
deadalnix
3

Dałem trochę opinii na stronie internetowej, która używała Javascript (jQuery) do interakcji i interfejsu użytkownika - były to dość proste animacje i manipulacje, ale wydajność na przyzwoitym komputerze była przerażająca.

Jednym z największych problemów z wydajnością jest używanie abstrakcyjnych poziomów wysokiego poziomu (takich jak jQuery) bez zrozumienia podstawowego modelu DOM i modelu animacji CSS3 (lub obszaru roboczego lub svg).

Jeśli nie wiesz, jak to zrobić bez abstrakcji, masz absolutną zerową wiedzę o tym, jakie techniki są szybkie lub wolne.

Ucz się JavaScript, ucz się DOM. Gdy poznasz tych dwóch i wiesz, co robią twoje abstrakcje, możesz je efektywnie wykorzystać. Oczywiście przez większość czasu zdajesz sobie sprawę, że abstrakcja jest wolna i po prostu rób to ręcznie bez biblioteki.

Raynos
źródło
1

Zaletą i wadą Javascript jest to, że jest on niezwykle elastyczny. To powiedziawszy, w rzeczywistości pozwala ci robić rzeczy, których prawdopodobnie nie powinieneś robić w wielu przypadkach.

Z recenzji kodu, w których byłem częścią, główne obawy związane są z renderowaniem CSS. W przypadku nowszych programistów JS mamy tendencję do dostrzegania zbyt wielu zmiennych używanych w zasięgu globalnym.

Nieprawidłowe zamknięcia często powodują przeciek pamięci. Jednak większość współczesnych frameworków JavaScript zapobiega tego rodzaju problemom, o ile kod podąża za nimi.

To chrząkanie
źródło
0

Oto szybki link, który znalazłem rok temu o pisaniu lepszego kodu jquery: http://net.tutsplus.com/tutorials/javascript-ajax/10-ways-to-instantly-increase-your-jquery-performance /

Jedną rzeczą, którą właśnie znalazłem w kodzie współpracowników, który zabijał wydajność, było buforowanie danych, które nie musiały być buforowane.

Przykład:

var table = $("#data").dataTable(.....);

DataTables to wtyczka jQuery, której używamy do tworzenia ładnych siatek. W każdym razie w tabeli było prawie 5 tys. Wierszy, zastosowanie wtyczki DataTables, a następnie zapisanie jej w zmiennej tabeli faktycznie spowodowało, że zarówno FireFox, jak i IE ostrzegły, że skrypt trwa zbyt długo. Morał tej historii, buforuj dane tylko w razie potrzeby.

Tyanna
źródło
1
Wygląda na to, że DataTables to naprawdę nieefektywna / słaba wtyczka, a nie problem z buforowaniem. 5k to nic.
Raynos
@Raynos: Powiedział 5 tysięcy wierszy , a nie 5 kilobajtów danych. „Rząd” może być bardzo dużą rzeczą.
Chris Farmer
@ChrisFarmer Jeśli „wiersz” jest bardzo dużą rzeczą, masz inny problem.
Raynos
-1

Z tego, co słyszałem, forpętle są obliczeniowo szybsze niż jQuery $.each().

pthesis
źródło
3
Czy to żart?
Raynos