17 komentářů k článku Zvyšte rychlost vašeho JS kódu:

  1. Naith

    Jaký je smysl první rady?
    Pokud potřebuji vyhodnotit „2“ porovnáno s 2 jako false, tak automaticky použiji ===. Pokud chci aby byl v tomto případe výsledek true, tak použiji ==. Navíc píšete, že pokud bude porovnání 2 == 2 bez rychlostního postihu, tak je to jedno.

    1. Petr NevyhoštěnýAutor příspěvku

      Re: Jaký je smysl první rady?
      Když pochází jeden operand zvenku (třeba jako vstupní parametr funkce), tudíž nemáte kontrolu nad datovým typem, a potřebujete, aby se striktně rovnal nějaké hodnotě, je škoda ztrácet čas typovými konverzemi.

  2. honzamarek88

    mikrooptimalizace
    No jo, ale pokud použiju nějaký framework jako Angular nebo Knockout a jiné, tak ty bottlenecky jsou někde úplně jinde a tyhle drobnosti už mě nevytrhnou.

    Pak mám pocit, že spousta tipů může přestat platit, když vyjde nová verze prohlížeče. Takže mi vůbec nedává smysl nadřazovat v těchto případech výkon nad čitelnost.

    1. Petr NevyhoštěnýAutor příspěvku

      Re: mikrooptimalizace
      Máte pravdu s těmi frameworky a v takovýchto aplikacích by se člověk měl zaměřit spíše na čitelnost a přehlednost, než aby aplikoval zmíněné techniky. Podle mě je jejich využití v nějakých menších javascriptových knihovnách, které pak budu třeba ve své aplikaci využívat. Dobrý příklad může být knihovny pro buildovací nástroje, které můžou pracovat nad velkým množstvím souborů a pro vývojáře je pak každá ušetřená milisekunda při buildu určitě potěšením.

      A co se týče nových verzí prohlížečů, máte pravdu, ale v mnohých testech na jsPerf, kde bylo otestováno více verzí prohlížečů, zůstává většinou vítěz stejný (ale objevují se i výjimky).

      1. karfcz

        Re: mikrooptimalizace
        Dobrý článek, škoda jen, že jsou ty techniky uvedné v pořadí od prakticky nejméně důležitých (dělení mocninami dvou se uplatní opravdu jen v extrémních případech) po velmi důležité (práce s poli).

        K těm polím bych dodal, že všechny funkcionální metody (map, reduce, atd.) lze napsat mnohem rychleji prostým cyklem, a to nejen proto, že se ušetří volání funkce, ale taky proto, že ne vždy potřebujeme robustní implementaci dle ECMA normy, která zahrnuje různé type checkingy a hlavně ošetření sparse arrays. Další pomalou metodou je Array.prototype.indexOf – pokud pracujeme s dense poli, pak je mnohonásobně rychlejší ruční for cyklus. To se v nových verzích prohlížečů asi jen tak nezmění.

        Podobné techniky jsem použil v jednom svém frameworku a opravdu to udělá dohromady klidně stovky procent výkonu. Jde o situace jako tisíce data-bindingů na stránce, kdy jsou podobné mikrooptimalizace znát. Takže pro knihovny a kritické části kódu rozhodně ano. Nevím, jak je na tom s optimalizacemi třeba právě Angular, pomalý je celkem dost. Knockout je naopak překvapivě docela svižný (aspoň co jsem testoval).

    2. KarelI

      Re: mikrooptimalizace
      Ostatne to s temi prohlizeci plati vsude. Kdyz clovek pise v asm, tak to jiny procesor muze resit jinak, v C++ jiny kompiler atd. Takze vzdy pouzivat profiler a menit jen veci ktere jsou nezbytne nutne.
      Uz jsem zazil pripady, kdy se jednou mikroopt. zkratil beh na 30%, u jineho programu na 18% casu, ale bez profileru bych na to neprisel. Take pak uz nebylo zrejme jak pokracovat, casy ve zbytku kodu byly ocekavatelne a nic nevycnivalo.

  3. Jirka Kosek

    Předčasná optimalizace
    V článku chybí asi nejdůležitější informace — při jakékoliv optimalizaci je nejprve potřeba najít úzké hrdlo aplikace, kde dochází k největšímu zdržení — zrychlovat jiné místo nepřinese požadovaný efekt.

    Nejprve je potřeba měřit pomocí profileru a pak teprve konat. Navíc v případě JS je potřeba měřit ve všech prohlížečích, protože různé JS enginy mají různé optimalizace.

    1. Petr NevyhoštěnýAutor příspěvku

      Re: Předčasná optimalizace
      Tento článek neměl být úplně o optimalizaci aplikace. Spíše jsem chtěl ukázat rychlejší varianty základních operací. Ale máte samozřejmě pravdu.

    1. Ladislav Thon

      Re:
      Samozřejmě správný postup je měření -> hypotéza -> kód -> goto 1. Tenhle článek nedává žádné informace o prvním kroku, ale může se hodit u toho druhého a třetího.

  4. Michal Čaplygin

    K procházení polí
    Za zmínku myslím stojí připomenout, že v případech, kdy se iteruje přes pole, které je ‚dense‘ (bez děr) a bez hodnot konvertcích na false, nabízí se pár postupů, které ani nejsou tolik znečitelňující, například:

    • Procházet pozpátku (pokud to zrovna nevadí): var i=arr.length; while(i--){arr[i]}, což se vyplatí zejména v IE.
    • Procházet s kontrolou pravdivosti přiřazené proměnné var el, i=-1; while(el=els[++i]){el} což je výkonově srovnatelné s ostatními navrhovanými obšírnostmi a pořád celkem neukecané.

    Podobná hustá pole bez nepravdivých hodnot jsou v běžné praxi myslím dost častá: všechna pole objektů což je mimo jiné i každý obyčejný NodeList vzniklý nějakým querySelectorem nebo document.getElementsByXY je přesně tenhle případ (jsPerf s iterací přes pole HTML prvků).

    Mimochodem, do jsPerfu aktuálně odkazovaném v článku se vloudila drobná chybka do čtvrtého testu: while (i++ < len) { arr[i]; } ‚přeskočí‘ první prvek a na konci ‚vrátí‘ undefined. (Mně se tohle taky stává každou chvíli :])

  5. e

    Bitové operácie sú však len na 32 bitové čísla, teda sa môže stať, že to v dôsledku tej optimalizácie „pretečie“.
    Overenie vlastnosti v objekte spôsobom obj[‚prop‘] !== undefined nerobí to isté ako ‚prop‘ in obj, lebo zahrňuje aj možnosť, že vlastnosť prop v obj existuje, no má hodnotu undefined.

  6. Radek_CZ

    Tomu, kdo se s JavaScriptem nesetkává každý den, může !!variable na moment lehce zamotat hlavu.

    Pokud pracuji s nějakým jazykem, měl bych se přeci naučit jeho syntaxi a vědět, jak funguje a jak se liší od ostatních. Nemůžu čekat, že jazyk pochopím na první pohled jen proto, že je C-like. A použití !! je prostě běžná praxe.

    Takže 16 >> 1 je to samé jako 16 / 2

    Tohle ale nebude fungovat u čísel přesahujících 32 bitů, neboť tento operátor pracuje s běžnými integery. Tím pádem ani nepočítá s desetinnou čárkou. Bylo by vhodné to zmínit.

    pozor však na určité záludnosti parseInt

    Tam žádné záludnosti nejsou. Človek holt jen musí vědět, že když vynechá druhý parametr, bude ho funkce odvozovat podle vstupu.

    metoda Math.floor(value)

    Která však při vstupu „-25.5“ nesprávně vrátí -26. Co se týče ostatních metod, tak společný problém je, že číslo neparsují, ale pouze string přetypovávají. (Tedy např. ze stringu „25 Kč“ nic nedostanu.) U str | 0 je stejný problém jako u bitového posunu, pracuje pouze s 32bitovým číslem. U stringu, kde vím, že je to prostě číslo, mohu jednoduše (a přehledně) použít str * 1.

    Naštěstí spojení s prázdným řetězcem vrátí ten samý výsledek, který by vrátilo přímé volání obj.toString().

    Mě by spíše fascinovala ta možnost, že by se to chovalo jinak. Při prvním přečtení mě to úplně zmátlo, osobně bych tohle z článku klidně odstranil nebo to napsal maličko jinak.

    Zapomeňte na funkcionální způsob arr.forEach(callback)

    Ale s tímhle zase pomalu. Funkcionální způsob bych rozhodně neodsuzoval, neboť může v mnoha případech velice zkrátit a zpřehlednit kód. Na místech, kde se neprovádí složité výpočty, to uvítám spíše než for konstrukci.

    nebo starší for (var i in arr)

    Co je, prosím pěkně, toto za blábol? Cyklus for-in nikdy nebyl určen k procházení indexovaných kolekcí.

    proto ho ani nepoužívejte k zjišťování přítomnosti vlastností v objektu (‚prop‘ in obj)

    Vřele doporučuji vyhledat si rozdíl mezi použitím in operátoru a porovnáním s hodnotou undefined.

    a sice pomocí konstrukce Array.prototype.push.apply(arr1, arr2)

    Opět bláboly. Metoda concat opravdu, podobně jako String.concat u stringů, slouží ke spojování polí. A je to jediná metoda spojování dvou polí do jednoho nového. Jedná se tedy o něco absolutně jiného než použití metody push, která pouze rozšíří první pole. Je to zvláštní, že vytváření nového objektu zabere více času, že? :-)

    1. e

      Re:

      Co se týče ostatních metod, tak společný problém je, že číslo
      neparsují, ale pouze string přetypovávají. (Tedy např. ze stringu „25
      Kč“ nic nedostanu.)
      Metódy parseInt a parseFloat však z reťazca „25 Kč“ vydolujú číslo 25.
      Ak je však v článku spomínaný „převod řetězců nebo desetinných čísel na celá čísla“,
      prečo sú v teste výrazy, čo to nerobia, ako +premenná, premenná*1 či metóda parseFloat?
      A prečo má druhý argument 10?
      Kde autor k tomu druhému argumentu prišiel?

      1. Radek_CZ

        Re:

        Metódy parseInt a parseFloat však z reťazca „25 Kč“ vydolujú číslo 25.

        Ano, to jsem přesně říkal. Pokud jde o parsování, je toto jediná možnost.

        prečo sú v teste výrazy, čo to nerobia, ako +premenná, premenná*1 či metóda parseFloat?

        Asi se jednalo o nějaký univerzálnější test, to bych neřešil.

        A prečo má druhý argument 10?

        Jak jsem psal výše, to člověk musí znát, pokud chce používat JS. Stačí se podívat do dokumentace. :-) Druhý parametr určuje číselnou soustavu. Např. výraz parseInt("f", 16) tedy vrátí číslo 15.

Napsat komentář

Tato diskuse je již příliš stará, pravděpodobně již vám nikdo neodpoví. Pokud se chcete na něco zeptat, použijte diskusní server Devel.cz

Zdroj: https://www.zdrojak.cz/?p=12328