Czy pętle są naprawdę szybsze w odwrotnej kolejności?

Słyszałem to kilka razy. Czy pętle JavaScript są naprawdę szybsze podczas liczenia wstecz? Jeśli tak, to dlaczego? Widziałem kilka przykładów zestawów testowych pokazujących, że odwrócone pętle są szybsze, ale nie mogę znaleźć żadnego wyjaśnienia dlaczego!

Zakładam, że dzieje się tak dlatego, że pętla nie musi już Oceniać właściwości za każdym razem, gdy sprawdza, czy jest skończona, i sprawdza tylko końcową wartość liczbową.

Tzn.

for (var i = count - 1; i >= 0; i--)
{
  // count is only evaluated once and then the comparison is always on 0.
}
Author: Anders, 2009-08-27

30 answers

Nie chodzi o to, że i-- jest szybszy niż i++. Właściwie, obie są równie szybkie.

To, co zajmuje czas w pętlach rosnących, to oszacowanie dla każdej i rozmiaru tablicy. W tej pętli:

for(var i = array.length; i--;)

Oceniasz .length tylko raz, kiedy deklarujesz i, natomiast dla tej pętli

for(var i = 1; i <= array.length; i++)

Oceniasz .length za każdym razem, gdy zwiększasz i, kiedy sprawdzasz, czy i <= array.length.

W większości przypadków nie powinieneś nawet martwić się o tego rodzaju optymalizację.

 849
Author: alestanis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-30 00:59:14

Ten facet porównał wiele pętli w javascript, w wielu przeglądarkach. Ma również zestaw testów , więc możesz je uruchomić samodzielnie.

We wszystkich przypadkach (chyba, że przegapiłem jedną w moim odczycie) najszybsza pętla to:

var i = arr.length; //or 10
while(i--)
{
  //...
}
 188
Author: Tom Ritter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-13 14:08:41

[19]} staram się dać szeroki obraz z tej odpowiedzi.

następujące myśli w nawiasach były moim przekonaniem, dopóki niedawno nie przetestowałem problemu:

[[w kategoriach języków niskiego poziomu Jak C/C++, kod jest kompilowany tak, że procesor ma specjalne warunkowe polecenie skoku, gdy zmienna jest zerowa (lub niezerowa).
Ponadto, jeśli zależy ci na takiej optymalizacji, możesz wybrać ++i zamiast i++, ponieważ ++i jest pojedynczym poleceniem procesora, podczas gdy i++ oznacza j=i+1, i=j.]]

Naprawdę szybkie pętle można wykonać, rozwijając je:

for(i=800000;i>0;--i)
    do_it(i);

Może być znacznie wolniejszy niż

for(i=800000;i>0;i-=8)
{
    do_it(i); do_it(i-1); do_it(i-2); ... do_it(i-7);
}

Ale przyczyny tego mogą być dość skomplikowane (wystarczy wspomnieć, że są problemy z preprocesorem poleceń procesora i obsługą pamięci podręcznej w grze).

W kategoriach języków wysokiego poziomu , takich jakJavaScript jak prosiłeś, możesz zoptymalizować rzeczy, jeśli polegasz w bibliotekach wbudowane funkcje do zapętlania. Niech zdecydują, jak najlepiej to zrobić.

W związku z tym, w JavaScript, sugerowałbym użycie czegoś takiego jak

array.forEach(function(i) {
    do_it(i);
});

Jest również mniej podatny na błędy i przeglądarki mają szansę zoptymalizować kod.

[uwaga: nie tylko przeglądarki, ale także masz miejsce na łatwą optymalizację, po prostu przedefiniuj funkcję forEach (w zależności od przeglądarki), aby korzystała z najnowszych najlepszych sztuczek! :) @A. M. K. mówi, że w szczególnych przypadkach warto raczej używając array.pop lub array.shift. Jeśli to zrobisz, Schowaj to za kurtynę. największą przesadą jest dodanie opcji do forEach, aby wybrać algorytm pętli.]

Ponadto, również dla języków niskiego poziomu, najlepszą praktyką jest użycie funkcji inteligentnej biblioteki do złożonych, zapętlonych operacji, jeśli jest to możliwe.

Te biblioteki mogą również umieszczać rzeczy (wielowątkowe) za twoimi plecami, a także wyspecjalizowani Programiści utrzymują je na bieżąco.

Zrobiłem trochę więcej kontroli i okazuje się, że w C / C++, nawet dla operacji 5e9 = (50,000x100,000), nie ma różnicy między pójściem w górę i w dół, jeśli testy są wykonywane na stałej, jak mówi @alestanis. (Wyniki jsperf są czasami niespójne, ale ogólnie mówią to samo: nie możesz zrobić wielkiej różnicy.)
Więc --i tak się składa, że to raczej "elegancka" rzecz. To tylko sprawia, że wyglądasz jak lepszy programista. :)

Z drugiej strony, dla-rozwinięcia w tej sytuacji 5e9, ma sprowadził mnie w dół z 12 SEK do 2,5 sek, gdy poszedłem o 10s, i do 2,1 sek, gdy poszedłem o 20s. to było bez optymalizacji, a optymalizacja przyniosła rzeczy w dół do niewymiernego mało czasu. :) (Rozwijanie można zrobić w mój sposób powyżej lub za pomocą i++, ale to nie przynosi rzeczy do przodu w JavaScript. )

W sumie: keep i--/i++ oraz ++i/i++ różnice w stosunku do rozmów kwalifikacyjnych, trzymaj się array.forEach lub innych złożonych funkcji bibliotecznych, gdy są dostępne. ;)

 127
Author: Barnabas Szabolcs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-19 17:49:49

i-- jest tak szybki jak i++

Poniższy kod jest tak szybki jak Twój, ale używa dodatkowej zmiennej:

var up = Things.length;
for (var i = 0; i < up; i++) {
    Things[i]
};

Zaleca się, aby nie oceniać rozmiaru tablicy za każdym razem. Dla dużych tablic można zobaczyć degradację wydajności.

 34
Author: sainiuc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-30 10:21:34

Ponieważ interesuje Cię ten temat, spójrz na post Grega Reimera na blogu o benchmarku pętli JavaScript, jaki jest najszybszy sposób na zakodowanie pętli w JavaScript?:

Zbudowałem zestaw testów porównawczych pętli dla różnych sposobów kodowania pętli w JavaScript. Jest ich już kilka, ale nie znalazłem żadnego, który rozpoznałby różnicę między natywnymi tablicami a kolekcjami HTML.

Możesz również wykonać a test wydajności w pętli poprzez otwarcie https://blogs.oracle.com/greimer/resource/loop-test.html (nie działa, jeśli JavaScript jest blokowany w przeglądarce na przykład przez NoScript ).

EDIT:

Nowszy benchmark stworzony przez Milana Adamovsky ' ego można wykonać w czasie wykonywania tutaj dla różnych przeglądarek.

Dla testów w Firefoksie 17.0 na Mac OS X 10.6 dostałem następującą pętlę:

var i, result = 0;
for (i = steps - 1; i; i--) {
  result += i;
}

Jako najszybszy poprzedzony przez:

var result = 0;
for (var i = steps - 1; i >= 0; i--) {
  result += i;
}

Przykład benchmarka.

 21
Author: dreamcrash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-15 03:47:26

Nie jest to -- lub ++, jest to operacja porównania. Z -- możesz użyć porównania z 0, podczas gdy z ++ musisz porównać go z długością. Na procesorze, compare with zero jest normalnie dostępny, podczas gdy compare with a finite integer wymaga odejmowania.

a++ < length

Jest w rzeczywistości skompilowany jako

a++
test (a-length)

Więc procesor po skompilowaniu zajmuje więcej czasu.

 19
Author: Dr BDO Adams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-19 17:37:02

Krótka odpowiedź

Dla normalnego kodu, szczególnie w języku wysokiego poziomu, takim jak JavaScript , nie ma różnicy wydajności w i++ i i--.

Kryterium wydajności jest użycie w pętli for i w instrukcji compare.

To dotyczy wszystkich języków wysokiego poziomu i jest w większości niezależne od korzystania z JavaScript. Wyjaśnienie jest wynikowym kodem asemblera w dolnej linii.

Szczegółowe Wyjaśnienie

Różnica wydajności może wystąpić w pętli. Tło jest takie, że na poziomie kodu asemblera widać, że compare with 0 jest tylko jedną instrukcją, która nie wymaga dodatkowego rejestru.

To porównanie jest wystawiane na każdym przejściu pętli i może skutkować wymierną poprawą wydajności.

for(var i = array.length; i--; )

Zostanie oceniony na pseudo kod tak:

 i=array.length
 :LOOP_START
 decrement i
 if [ i = 0 ] goto :LOOP_END
 ... BODY_CODE
 :LOOP_END

Zauważ, że 0 jest dosłownym, czyli innymi słowy, stała wartość.

for(var i = 0 ; i < array.length; i++ )

Zostanie oceniony do pseudo kodu w ten sposób (normalna optymalizacja interpretera):

 end=array.length
 i=0
 :LOOP_START
 if [ i < end ] goto :LOOP_END
 increment i
 ... BODY_CODE
 :LOOP_END

Zauważ, że end jest zmienną wymagającą rejestruCPU. Może to wywoływać dodatkowe zamiany rejestru w kodzie i wymaga droższego porównania w if.

Tylko moje 5 centów

Dla języka na wysokim poziomie, czytelności, co ułatwia konserwacja, jest ważniejsza jako niewielka poprawa wydajności.

Normalnie klasyczna iteracja Z Tablicy od początku do końca jest lepsza.

Szybsza iteracja Z Tablicy end to start powoduje powstanie niepożądanej odwrotnej sekwencji.

Post scriptum

Jak zapytano w komentarzu: różnica --i i i-- jest w ocenie i przed lub po spadku.

Najlepszym wyjasnieniem jest aby go wypróbować; -) oto przykład Bash.

 % i=10; echo "$((--i)) --> $i"
 9 --> 9
 % i=10; echo "$((i--)) --> $i"
 10 --> 9
 16
Author: H.-Dirk Schmitt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-19 18:14:02

Widziałem to samo zalecenie w Sublime Text 2.

Jak już zostało powiedziane, głównym ulepszeniem nie jest ocena długości tablicy przy każdej iteracji w pętli for. Jest to dobrze znana technika optymalizacji i szczególnie skuteczna w JavaScript, gdy tablica jest częścią dokumentu HTML (wykonując for dla wszystkich elementów li).

Na przykład,

for (var i = 0; i < document.getElementsByTagName('li').length; i++)

Jest znacznie wolniejszy niż

for (var i = 0, len = document.getElementsByTagName('li').length; i < len; i++)

From where I ' m standing, the główną poprawą w formularzu w twoim pytaniu jest fakt, że nie deklaruje dodatkowej zmiennej (len w moim przykładzie)

Ale jeśli O mnie chodzi, nie chodzi o optymalizację i++ vs i--, ale o to, aby nie musieć Oceniać długości tablicy przy każdej iteracji (możesz zobaczyć test benchmarkowy na jsperf).

 15
Author: BBog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-31 10:10:02

Myślę, że nie ma sensu mówić, że {[2] } jest szybsze niż i++ w JavaScript.

Po pierwsze , to całkowicie zależy od implementacji silnika JavaScript.

Po Drugie, pod warunkiem, że najprostsze konstrukcje JIT ' a i przetłumaczone na natywne instrukcje, to i++ vs i-- będzie całkowicie zależeć od procesora, który go wykonuje. Oznacza to, że na ramionach (telefonach komórkowych) szybciej jest zejść do 0, ponieważ dekrementacja i porównanie do zera są wykonywane w jednym Instrukcja.

Prawdopodobnie, myślałeś, że jeden jest bardziej marnotrawny niż drugi, ponieważ sugerowany sposób jest

for(var i = array.length; i--; )

Ale sugerowany sposób nie dlatego, że jeden szybciej niż drugi, ale po prostu dlatego, że jeśli piszesz

for(var i = 0; i < array.length; i++)

Następnie przy każdej iteracji array.length trzeba było ocenić (inteligentniejszy silnik JavaScript może się zorientować, że pętla nie zmieni długości tablicy). Mimo, że wygląda to jak proste stwierdzenie, to w rzeczywistości jest to jakaś funkcja, która jest wywoływana pod maską przez silnik JavaScript.

Innym powodem, dla którego i-- można uznać za "szybsze" jest to, że silnik JavaScript musi przydzielić tylko jedną wewnętrzną zmienną do sterowania pętlą (zmienną do var i). Jeśli w porównaniu do tablicy.length lub do jakiejś innej zmiennej wtedy nie musiał być więcej niż jedna zmienna wewnętrzna do sterowania pętli, a liczba zmiennych wewnętrznych są ograniczone aktywów silnika JavaScript. Im mniej zmiennych jest używanych w pętli, tym większa szansa na optymalizacja. Dlatego i-- można uznać za szybsze...

 14
Author: Pavel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-08 19:54:14

Ponieważ żadna z innych odpowiedzi nie odpowiada na twoje konkretne pytanie (ponad połowa z nich pokazuje przykłady C i omawia języki niższego poziomu, twoje pytanie dotyczy JavaScript) postanowiłem napisać własne.

Więc proszę bardzo:

Prosta odpowiedź: i-- jest na ogół szybszy, ponieważ nie musi uruchamiać porównania do 0 za każdym razem, Wyniki testów na różnych metodach są poniżej:

Wyniki badań: jako "udowodnione" przez to jsPerf, arr.pop() jest w rzeczywistości najszybszą pętlą. Ale, skupiając się na --i, i--, i++ i ++i Jak zadałeś w swoim pytaniu, oto wyniki jsperf (są one z wielu jsPerf ' s, patrz źródła poniżej):

--i i i-- są takie same w Firefoksie, podczas gdy i-- jest szybsze w Chrome.

W Chrome podstawowa pętla for (for (var i = 0; i < arr.length; i++)) jest szybsza niż i-- i --i, podczas gdy w Firefoksie jest wolniejsza.

Zarówno w Chrome jak i Firefox buforowany arr.length jest znacznie więcej informacji na ten temat można znaleźć na stronie .]}

Bez znaczącej różnicy, ++i jest szybszy niż i++ w większości przeglądarek, AFAIK, nigdy nie jest odwrotnie w żadnej przeglądarce.

Krótsze podsumowanie: arr.pop() jest najszybszą pętlą; dla wymienionych pętli {[0] } jest najszybszą pętlą.

Źródła: http://jsperf.com/fastest-array-loops-in-javascript/15, http://jsperf.com/ipp-vs-ppi-2

I mam nadzieję, że to odpowie na twoje pytanie.

 14
Author: A.M.K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-25 19:50:16

Zależy to od umieszczenia tablicy w pamięci i współczynnika trafień stron pamięci podczas uzyskiwania dostępu do tej tablicy.

W niektórych przypadkach dostęp do elementów tablicy w kolejności kolumn jest szybszy niż kolejność wierszy ze względu na wzrost współczynnika trafień.

 13
Author: Akbar Bayati,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-12 12:55:47

Ostatni raz martwiłem się o to, kiedy pisałem 6502 Montaż (8-bitowy, tak!). Dużym zyskiem jest to, że większość operacji arytmetycznych (zwłaszcza dekrementacji) zaktualizowała zestaw flag, jedną z nich był Z, wskaźnik "osiągnął zero".

Na końcu pętli wykonałeś dwie instrukcje: DEC (decrement) i JNZ (jump if not zero), nie trzeba porównywać!

 11
Author: Javier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-19 17:55:16

W skrócie: nie ma absolutnie żadnej różnicy w robieniu tego w JavaScript.

Po pierwsze, możesz przetestować go samodzielnie:

Nie tylko możesz przetestować i uruchomić dowolny skrypt w dowolnej bibliotece JavaScript, ale także masz dostęp do całej masy wcześniej napisanych skryptów, jak również możliwość zobaczenia różnic między czasem wykonania w różnych przeglądarkach na różnych platformach.

Jak widać, nie ma różnicy między wydajnością w żadnym środowisku.

Jeśli chcesz poprawić wydajność swojego skryptu, możesz spróbować zrobić:

  1. miej polecenie var a = array.length; tak, że nie będziesz obliczał jego wartości za każdym razem w pętli
  2. Do rozwijania pętli http://en.wikipedia.org/wiki/Loop_unwinding

Ale musisz zrozumieć, że poprawa, którą możesz uzyskać, będzie tak nieistotna, że w większości przypadków nie powinieneś o nią nawet dbać.

Moja własna opinia, dlaczego tak błędne przekonanie (Dec vs Inc) pojawił

Dawno, dawno temu istniała powszechna Instrukcja maszynowa, DSZ (Decrement and Skip on Zero). Ludzie, którzy programowali w języku asemblera używali tej instrukcji do implementacji pętli w celu zapisania Zarejestruj się. Teraz te starożytne fakty są przestarzałe i jestem prawie pewien, że nie dostaniesz żadnej poprawy wydajności w żadnym języku za pomocą tego pseudo poprawy.

Myślę, że jedynym sposobem, w jaki taka wiedza może się rozprzestrzeniać w naszych czasach, jest przeczytanie kodu cudzej osoby. Zobacz taką konstrukcję i zapytaj dlaczego została wdrożona, a tutaj odpowiedź: "poprawia wydajność, ponieważ porównuje się do zera". Oszołomiła Cię wyższa wiedza kolegi i myślisz, że wykorzystasz ją, aby być dużo mądrzejszy : -)

 8
Author: Salvador Dali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-19 18:04:47

To może być wyjaśnione przez JavaScript (i wszystkie języki) ostatecznie zamienione w opcodes uruchomić na CPU. Procesory zawsze mają jedną instrukcję do porównywania z zerem, co jest cholernie szybkie.

Na marginesie, jeśli możesz zagwarantować, że count jest zawsze >= 0, możesz uprościć do:

for (var i = count; i--;)
{
  // whatever
}
 7
Author: searlea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-27 11:58:14

Nie jest to zależne od znaku -- lub ++, ale zależy to od warunków, które zastosujesz w pętli.

Na przykład: pętla jest szybsza, jeśli zmienna ma wartość statyczną, niż jeśli pętla sprawdza warunki za każdym razem, jak długość tablicy lub inne warunki.

Ale nie martw się o tę optymalizację, ponieważ tym razem jej efekt jest mierzony w nanosekundach.

 7
Author: Arvind Kanjariya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-19 17:52:06

for(var i = array.length; i--; ) nie jest dużo szybszy. Ale kiedy zamienisz array.length na super_puper_function(), może to być znacznie szybciej (ponieważ jest wywoływany w każdej iteracji). To jest różnica.

Jeśli zamierzasz to zmienić w 2014 roku, nie musisz myśleć o optymalizacji. Jeśli zamierzasz go zmienić za pomocą "Szukaj i zamień", nie musisz myśleć o optymalizacji. Jeśli nie masz czasu, nie musisz myśleć o optymalizacji. Ale teraz masz czas, żeby to przemyśleć.

P. S.: i-- nie jest szybszy niż i++.

 7
Author: Dmitry Isaev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-19 17:53:57

Czasami dokonywanie bardzo drobnych zmian w sposobie pisania kodu może znacząco wpłynąć na szybkość działania kodu. Jednym z obszarów, w którym drobna zmiana kodu może mieć duży wpływ na czas wykonania, jest pętla for, która przetwarza tablicę. W przypadku, gdy tablica zawiera elementy na stronie (np. przyciski radiowe) zmiana ma największy efekt, ale i tak warto tę zmianę zastosować nawet wtedy, gdy tablica jest wewnętrzna do Javascript kod.

Konwencjonalny sposób kodowania pętli for do przetwarzania tablicy lis w ten sposób:

for (var i = 0; i < myArray.length; i++) {...

Problem z tym polega na tym, że ocena długości tablicy przy użyciu myArray.długość wymaga czasu, a sposób, w jaki zakodowaliśmy pętlę oznacza, że ta ocena musi być wykonywana za każdym razem wokół pętli. Jeżeli tablica zawiera 1000 elementów, wtedy długość tablicy będzie obliczana 1001 razy. Gdybyśmy patrzyli na przyciski radiowe i mieli mój formularz.myButtons.długość wtedy to ocena potrwa jeszcze dłużej, ponieważ odpowiednia Grupa przycisków w określonym formularzu musi być najpierw zlokalizowana, zanim długość będzie mogła być oceniana za każdym razem wokół pętli.

Oczywiście nie oczekujemy, że długość tablicy zmieni się podczas przetwarzania, więc wszystkie te przeliczniki długości dodają niepotrzebnie do czasu przetwarzania. (Oczywiście jeśli wewnątrz pętli znajduje się kod, który dodaje lub usuwa wpisy tablicy, to rozmiar tablicy może się zmieniać pomiędzy iteracji, a więc nie możemy zmienić kodu, który go testuje)

Co możemy zrobić, aby poprawić to dla pętli, w której rozmiar jest stały, to ocenić długość raz na początku pętli i zapisać ją w zmiennej. Możemy następnie przetestować zmienną, aby zdecydować, kiedy zakończyć pętlę. Jest to znacznie szybsze niż obliczanie długości tablicy za każdym razem, szczególnie gdy tablica zawiera więcej niż kilka wpisów lub jest częścią strony internetowej.

Kod do tego jest:

for (var i = 0, var j = myArray.length; i < j; i++) {...

Więc teraz oceniamy rozmiar tablicy tylko raz i testujemy nasz licznik pętli przeciwko zmiennej, która utrzymuje tę wartość za każdym razem wokół pętli. Ta dodatkowa zmienna może być dostępna znacznie szybciej niż rozmiar tablicy, a więc nasz kod będzie działał znacznie szybciej niż wcześniej. Mamy tylko jedną dodatkową zmienną w naszym skrypcie.

Często nie ma znaczenia w jakiej kolejności przetwarzamy tablicę, o ile wszystkie wpisy w tablicy zostaną przetworzone. Gdzie to jest przypadek możemy zrobić nasz kod nieco szybciej, usuwając dodatkową zmienną, którą właśnie dodaliśmy i przetwarzając tablicę w odwrotnej kolejności.

Końcowy kod, który przetwarza naszą tablicę w najbardziej efektywny możliwy sposób to:

for (var i = myArray.length-1; i > -1; i--) {...

Ten kod nadal oblicza rozmiar tablicy tylko raz na początku, ale zamiast porównywać licznik pętli ze zmienną porównujemy go ze stałą. Ponieważ stała jest jeszcze bardziej efektywna w dostępie niż zmienna, a ponieważ mamy mniej instrukcji assignment niż wcześniej nasza trzecia wersja kodu jest teraz nieco bardziej wydajna niż druga wersja i znacznie bardziej wydajna niż pierwsza.

 5
Author: Sid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-31 06:52:08

Zrobiłem porównanie na jsbench.

Jak zauważył alestani, jedną rzeczą, która wymaga czasu w pętlach rosnących, jest ocena, dla każdej iteracji, wielkości tablicy. W tej pętli:

for ( var i = 1; i <= array.length; i++ )

Oceniasz .length za każdym razem, gdy zwiększasz i. W tym:

for ( var i = 1, l = array.length; i <= l; i++ )

Oceniasz .length tylko raz, kiedy deklarujesz i. W tym:

for ( var i = array.length; i--; )

Porównanie jest niejawne, dzieje się tuż przed spadkiem i, A kod jest bardzo czytelne. Jednak to, co może zrobić wspaniałą różnicę, to to, co umieścisz w pętli.

Pętla z wywołaniem funkcji (zdefiniowanej gdzie indziej):

for (i = values.length; i-- ;) {
  add( values[i] );
}

Pętla z kodem inlined:

var sum = 0;
for ( i = values.length; i-- ;) {
  sum += values[i];
}

Jeśli możesz wstawić kod, zamiast wywoływać funkcję, bez utraty czytelności, możesz mieć pętlę o rząd wielkości szybciej!


Uwaga : ponieważ przeglądarki są coraz dobre w inlining proste funkcje, to naprawdę zależy od tego, jak skomplikowane Twój kod jest. Tak więc, profil przed optymalizacją, ponieważ

  1. wąskie gardło może być gdzie indziej (ajax, reflow, ...)
  2. możesz wybrać lepszy algorytm
  3. możesz wybrać lepszą strukturę danych

Ale pamiętaj:

Kod jest pisany dla ludzi do czytania, a nawiasem mówiąc tylko dla maszyn do wykonywania.

 5
Author: Spyryto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-23 12:57:11

Sposób, w jaki teraz to robisz, nie jest szybszy (poza tym, że jest to pętla nieokreślona, myślę, że chciałeś to zrobić i--.

Jeśli chcesz zrobić to szybciej zrób:

for (i = 10; i--;) {
    //super fast loop
}

Oczywiście nie zauważyłbyś tego na tak małej pętli. Powodem, dla którego jest to szybsze, jest to, że zmniejszasz i sprawdzając, czy jest to " prawda "(ocenia się na" fałsz", gdy osiągnie 0)

 4
Author: peirix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-27 11:57:44

W wielu przypadkach nie ma to zasadniczo nic wspólnego z faktem, że procesory mogą porównać do zera szybciej niż inne porównania.

Dzieje się tak dlatego, że tylko kilka silników Javascript (tych z listy JIT) faktycznie generuje kod języka maszynowego.

Większość silników Javascript buduje wewnętrzną reprezentację kodu źródłowego, który następnie interpretuje (aby dowiedzieć się, jak to jest, zajrzyj na dół tej strony na Firefoksie SpiderMonkey ). Ogólnie rzecz biorąc, jeśli fragment kodu robi praktycznie to samo, ale prowadzi do prostszej reprezentacji wewnętrznej, będzie działał szybciej.

Należy pamiętać, że przy prostych zadaniach, takich jak dodawanie/odejmowanie jednej ze zmiennych lub porównywanie zmiennej do czegoś, obciążenie interpretera przenoszącego się z jednej wewnętrznej "instrukcji" do następnej jest dość wysokie, więc im mniej "instrukcji", które są używane wewnętrznie przez silnik JS, tym lepiej.

 3
Author: Artelius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-08 08:36:26

Cóż, nie znam się na JavaScript, powinno to być tylko kwestią ponownej oceny długości tablicy i może coś wspólnego z tablicami asocjacyjnymi (jeśli tylko zmniejszasz, jest mało prawdopodobne, aby nowe wpisy musiały być przydzielane - jeśli tablica jest gęsta, to znaczy. ktoś może do tego zoptymalizować).

W asemblacji niskiego poziomu istnieje instrukcja loopingu, zwana DJNZ (decrement and jump if non-zero). Więc dekrementacja i skok są w jednej instrukcji, dzięki czemu możliwe ever-so-nieco szybciej niż INC i JL / JB (increment, jump if less than / jump if below). Ponadto porównywanie z zerem jest prostsze niż porównywanie z inną liczbą. Ale wszystko to jest naprawdę marginalne i zależy również od architektury docelowej (może zrobić różnicę np. na Arm w smartfonie).

Nie spodziewałbym się, że te niskopoziomowe różnice będą miały tak wielki wpływ na języki interpretowane, po prostu nie widziałem DJNZ wśród odpowiedzi, więc pomyślałem, że podzielę się ciekawą myślałem.

 3
Author: the swine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-30 12:54:06

It used to be said that -- I was faster (in C++) because there is only one result, the decremented value. i -- musi zapisać zmniejszoną wartość z powrotem do i, a także zachować pierwotną wartość jako wynik (j = i--;). W większości kompilatorów używało to dwóch rejestrów, a nie jednego, co mogło spowodować, że inna zmienna musi zostać zapisana do pamięci, a nie zachowana jako zmienna rejestru.

Zgadzam się z tymi, którzy powiedzieli, że to nie robi różnicy te dni.

 3
Author: Ant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-30 18:09:18

W bardzo prostych słowach

"i -- i++. Właściwie, obie są w tym samym czasie".

Ale w tym przypadku, gdy masz operację przyrostową.. procesor ocenia .długość każdej zmiennej czasowej jest zwiększana o 1, a w przypadku zmniejszania.. szczególnie w tym przypadku, będzie oceniać .Długość tylko raz, aż dostaniemy 0.

 3
Author: Ravi_Parmar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-31 11:00:14

++ vs. -- nie ma znaczenia, ponieważ JavaScript jest językiem interpretowanym, a nie językiem skompilowanym. Każda instrukcja przekłada się na więcej niż jeden język maszynowy i nie powinieneś dbać o krwawe szczegóły.

Ludzie, którzy mówią o użyciu -- (lub ++) w celu efektywnego wykorzystania instrukcji montażu są w błędzie. Te instrukcje dotyczą arytmetyki całkowitej i nie ma żadnych liczb całkowitych w JavaScript, tylko liczby .

Powinieneś napisać czytelny kod.

 3
Author: Salman A,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-31 13:42:47

Po pierwsze, i++ i i-- zajmują dokładnie ten sam czas w każdym języku programowania, w tym w JavaScript.

Poniższy kod zajmuje dużo inny czas.

szybko:

for (var i = 0, len = Things.length - 1; i <= len; i++) { Things[i] };

powoli:

for (var i = 0; i <= Things.length - 1; i++) { Things[i] };

Dlatego też poniższy kod zajmuje inny czas.

szybko:

for (var i = Things.length - 1; i >= 0; i--) { Things[i] };

powoli:

for (var i = 0; i <= Things.length - 1; i++) { Things[i] };

P. S. Slow jest powolny tylko dla kilku języków (silniki JavaScript) ze względu na optymalizację kompilatora. Najlepszym sposobem jest użycie ' (lub"=") i " -- i "zamiast" i-- " .

 3
Author: Dmitry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-17 23:39:25

Niewiele czasu pochłania ja -- lub ja++. Jeśli zagłębisz się w architekturę procesora, ++ jest szybsza niż --, ponieważ operacja -- będzie uzupełniać 2, ale dzieje się to wewnątrz sprzętu, więc będzie to szybkie i bez większej różnicy między ++ i -- również te operacje są uważane za najmniej czasu spędzonego w procesorze.

Pętla for przebiega tak:

  • Zainicjalizuj zmienną raz na zaczynaj.
  • Sprawdź ograniczenie w drugim operandie pętli, <, >, <=, itd.
  • następnie zastosuj pętlę.
  • przyrost pętli i pętla ponownie rzucają te procesy ponownie.

Więc,

for (var i = Things.length - 1; i >= 0; i--) {
    Things[i]
}; 

Obliczy długość tablicy tylko raz na początku i nie jest to dużo czasu, ale

for(var i = array.length; i--; ) 

Obliczy długość każdej pętli, więc zajmie to dużo czasu.

 3
Author: Omar Freewan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-19 18:10:27

Najlepszym podejściem do odpowiedzi na tego rodzaju pytanie jest rzeczywiście spróbować. Skonfiguruj pętlę, która liczy milion iteracji i rób to w obie strony. Czas obie pętle, i porównać wyniki.

Odpowiedź będzie prawdopodobnie zależeć od używanej przeglądarki. Niektóre będą miały inne wyniki niż inne.

 1
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-27 11:58:44

Love it, lots of marks up but no answer: d

Po prostu porównanie z zerem jest zawsze najszybszym porównaniem

Więc (a==0) jest w rzeczywistości szybsze przy zwracaniu True niż (a = = 5)

Jest mały i nieistotny, a przy 100 milionach wierszy w zbiorze jest mierzalny.

Tzn w pętli można powiedzieć gdzie i

W pętli w dół Możesz mówić gdzie i > = 0 i być zamiast tego.

Porównanie jest szybsze. Nie "kierunek" pętli.

 1
Author: Robert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-27 12:08:46

POMÓŻ INNYM UNIKNĄĆ BÓLU GŁOWY - - - ZAGŁOSUJ!!!

Najpopularniejsza odpowiedź na tej stronie nie działa dla Firefoksa 14 i nie przechodzi przez jsLinter. pętle "while" wymagają operatora porównania, a nie przypisania. Działa na chrome, safari, a nawet ie. Ale umiera w Firefoksie.

TO JEST ZEPSUTE!
var i = arr.length; //or 10
while(i--)
{
  //...
}
TO ZADZIAŁA! (działa na Firefoksie, przechodzi przez jsLinter)
var i = arr.length; //or 10
while(i>-1)
{
  //...
  i = i - 1;
}
 1
Author: mrbinky3000,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-17 17:43:44

To tylko zgadywanie, ale może dlatego, że łatwiej jest procesorowi porównać coś z 0 ( i >= 0 ) zamiast z inną wartością (i

 1
Author: Rorchackh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-30 10:13:01