« 1 2 »
Autor Zpráva
aDAm
Profil
Zdravím,
neměl by někdo z vás tip na nějakou appku pokud existuje co by dokazala otestovat moje js v aplikaci? Řeším totiž problém rychlost samotné aplikace na slabších PC kde se stává téměř nepoužitelnou :( Jedná se o interní appku která má vše řešeno na pozadí a na slabších PC narážím na problém strašně pomalé odezvy na kliknutí.

Prošel jsem x návodů jak zrychlit JS založeném na jQuery, aplikoval je ale stále se nemůžu dostat na optimální rychlost. Dá se toto vytěžování nějak odladit?
Kcko
Profil
http://jsperf.com/

Si zkontroluj konkrétní věci
pcmanik
Profil
aDAm:
Bez živej ukážky sa ťažko radí.

Ale čo môžeš urobiť:
Netreba skutočne na všetko jQuery, väčšina vecí sa dá riešiť aj pomocou "čistého" javascriptu.
Zmenšiť množstvo udalostí na stránke ak je to možné.

Ale toto sú zase len všeobecné tipy, aby sme ti priamo poradili potrebujeme živú ukážku.
aDAm
Profil
Kcko:
no na tohle sem už narazil ale zatím mě nenapadá jak tam udělat testcase aby to otestovalo to co potřebuji

pcmanik:
no je mě jasné že bez ukázky se radí blbě, ale ta appka není přístupná z venku.
jQuery tam mám proto, protože s jeho pomocí věším jednotlivé události co se na té stránce dějí, resp vše je obaleno jako pluginy které se pak věší na jednotlivé elementy.
No události jsem minimalizoval, vyházel jsem live, delegate apod a využil nové ON a OFF eventy. Tohle přineslo nějaké zlepšení ale stále to není to prvavé
final
Profil
skús dať aspoň pár riadkov kódu
aDAm
Profil
final:
fuu no toho kodu je už x set řádků, tak snad jen kousek:

(function($) {
    var plg = function() {};
    
    $.extend(plg.prototype, {
        name: "BrowseItems",
        
        // Datagrid browsing init
        initialize: function(element) {
            this.element = element;

            // Add plugin info
            $.data(element, 'BrowseItems', 'BrowseItems');

            // Get datagrid element
            this.dataGrid = $("div.moduledata", element);
            
            // Datagrid ordering
            this.dataGridOrdering();
            // Datagrid filtering
            this.dataGridFiltering();
            // Datagrid pagination
            this.dataGridPagination();
            // Item priority buttons
            this.updateRecordPriority();
            // Data massactions
            this.massActions();
            // Table items action buttons
            this.actionButtons();
        },
        
        // Datagrid ordering
        dataGridOrdering: function() {
            var obj = this;

            if ( !$("a.tableOrdering", this.element).exists() ) return;
            
            this.dataGrid.on('click', 'table.adminlisttable thead tr.headings a.tableOrdering', function(e){
                e.preventDefault();

                // Get ordering options
                var options = $(this).data('ordering');
                
                // Set order dir and order by
                $('input[rel=order_by]', obj.element).val(options.orderBy);
                $('input[rel=order_dir]', obj.element).val(options.orderDir);
                
                // Clear system message
                ipubApplication.core.elements.messagebox
                    .SystemMessages('clearMessageBox');
                
                // Get new datagrid data
                obj.refreshDatagridList();
                
                return false;
            });
        },
        
        // Datagrid filtering
        dataGridFiltering: function() {
            var obj = this;
            
            // Data filter by selection
            this.dataGrid.on('click', 'tbody.dataTable a.filterByItem', function(e){
                e.preventDefault();
                
                var options        = $(this).data('filter'),
                    filterElm    = $('select[name*="filter\\[' + options.filter + '\\]"]', obj.element);
                
                if ( filterElm.exists() ) {
                    filterElm.selectOptions(options.filterValue);
                    
                    // Clear system message
                    ipubApplication.core.elements.messagebox
                        .SystemMessages('clearMessageBox');
                    
                    // Get new datagrid data
                    obj.refreshDatagridList();
                }
                
                return false;
            });
            
            // Unset filter button
            this.dataGrid.on('click', 'a[name=unsetfilter]', function(e){
                e.preventDefault();
                
                // Reset input fields
                $('input[type=text][name*=filter\\[]', obj.element).each(function() {
                    $(this).val('');
                });
        
                // Reset selectboxes
                $('select[name*=filter\\[]', obj.element).each(function() {
                    $(this).selectOptions($("option:first", $(this)).val(), true);
                });
                
                // Clear system message
                ipubApplication.core.elements.messagebox
                    .SystemMessages('clearMessageBox');
                
                // Get new datagrid data
                obj.refreshDatagridList();
                
                return false;
            });
            
            // Set filter button
            this.dataGrid.on('click', 'a[name=setfilter]', function(e){
                e.preventDefault();
                
                // Clear system message
                ipubApplication.core.elements.messagebox
                    .SystemMessages('clearMessageBox');
                
                // Get new datagrid data
                obj.refreshDatagridList();
                
                return false;
            });
        
            // Filter inputs
            this.dataGrid.on('keypress', 'table.adminlisttable thead tr.filter input[name*="filter"]', function(e){
                // Get pressed key code
                var code = (e.keyCode ? e.keyCode : e.which)

                 if ( code == 13 ) {
                     e.preventDefault();
                     
                    // Clear system message
                    ipubApplication.core.elements.messagebox
                        .SystemMessages('clearMessageBox');
                    
                    // Get new datagrid data
                    obj.refreshDatagridList();
                    
                    return false;
                 }
            });
            
            // Select filter input
            this.dataGrid.on('change', 'table.adminlisttable thead tr.filter select[name*="filter"]', function(e){
                e.preventDefault();
                
                // Clear system message
                ipubApplication.core.elements.messagebox
                    .SystemMessages('clearMessageBox');
                
                // Get new datagrid data
                obj.refreshDatagridList();
                
                return false;
            });
        }
    });
    
    $.fn[plg.prototype.name] = function() {
        var args = arguments,
            method = args[0] ? args[0] : null;
            
        return this.each(function() {
            var obj = $(this);
            
            if ( plg.prototype[method] && obj.data(plg.prototype.name) && method != "initialize" ) {
                obj.data(plg.prototype.name)[method].apply(obj.data(plg.prototype.name), Array.prototype.slice.call(args, 1));
                
            } else if (!method || $.isPlainObject(method)) {
                var elm = new plg;
                
                plg.prototype.initialize && elm.initialize.apply(elm, $.merge([obj], args));
                obj.data(plg.prototype.name, elm);
                
            } else {
                $.error("Method " + method + " does not exist on jQuery." + plg.name)
            }
        });
    }
    
})(jQuery);

tenhle objekt má ještě několik dalších metod a takovýchto pluginů je tam několik.
pcmanik
Profil
aDAm:
Tie komplikované selektory sa nedajú zjednodušiť? Input s atribútom rel nevyužíva žiadnu nativnu implementáciu, takže je tiež pomalé.

Na riadku 66. Sa dá použiť priamo this.getAttribute('data-filter'), co je rychlejsie.

Riadok 89 sa dá zapísať ako this.value = '';

Takychto mikro optimalizacii je tam viacero.

Pomocou jQuery mozes ziskat element a zapisom $('element')[0] môžes využívať priamo funkcie js a nepotrebuješ k tomu jQuery, ktoré je pomalšie.
aDAm
Profil
pcmanik:
díky za tip, zkusím.

Ale konkrétně ten řádek 66 je takto schválně, protože mě to vrátí už rozparsovaný objekt s nastavením takže nemusím dělat dodatečné rozbití do objektu.
Ty komplikované selectory máš namysli v těch ON eventech? jako pokud to zvýší rychlost tak tam může zustat klidně poslední selector.
pcmanik
Profil
aDAm:
Použi užitočný nástroj, ktorý ti poradil Kcko a sám uvidíš, ako veľký rozdiel to je.
peta
Profil
aDAm:
Jak vykonny je stroj, do ktereho ho davas? Procesor, pamet, disk, virtualni pamet, ...
Jaky js do toho davas? jQuery - rychlost
Jak casto ten JS spoustis?
Jaky typ prohlizece na tom pc bezi? Mam negativni zkusenostmi s FF3 a vys, FF2.4 na slabsim pc funguje krasne.

Na stary pc bych nedaval zadny js nebo jen minimum. S jquery muzou byt potize. Jestli to chces teda provozovat, tak doporucuji nejdriv spustit scriptik na detekci verze nebo si testnout rychlost a vykon prohlizece a pak pripadne natahnout dalsi javascripty nebo radeji uplne vypnout (tagScript.src="http:/...").
aDAm
Profil
peta:
Tak ta pomalost je detekována na obyč netbooku EEEčko od asusu, procák nějaký atom, ramka 2GB
Jak jaký JS? No natáhne si to poslední jQuery, jQuery UIčko, pak nějaké custom pluginy pro jQuery a pak x pluginů te appky.
Ten JS se spouští vždy, jsou prostě pro chod té appky. Příklad uvedený výše např. pracuje s výpisem dat (stránkování, filtrování, pořadí atd)
Na tom netbooku je poslendí verze FF, Chrome se chová o něco málo lépe ale pořád to není žádná hitparáda

No JS musí být k dispozici, bez JS ta appka nefunguje, vše se prostě řídí s pomocí JS (otvírání záložek s obsahem, výpis dat do tabulek, editace dat atd.) Jako na klasika noromálním PC není problém, ale pokud je někdo na cestách a má sebou jen takovou kapesní srandu v podobě EEEčka tak je problém v té appce pracovat.
panther
Profil
aDAm:
porad nikdo nevi, o cem se tu presne bavime, tak nevim, proc by mela tato diskuse pokracovat - bez znalosti konkretni stranky zadnou radu dostat nemuzes. Neni to mozne, ne, ze by ti nikdo poradit nechtel.

Snad se jen smirit s tim, ze kdyz naplacas do stranky 1MB JavaScriptu a mas v nem spoustu drobnych chyb, v zivote to rychle bezet nemuze. Kazdy pocitac ma nekde sve limity, EEE je ma v teto tebou napsane aplikaci (cim chci rici, ze kdyby se napsala lepe, bezela by i na EEE).
Chamurappi
Profil
Reaguji na aDAma:
vyházel jsem live, delegate apod a využil nové ON a OFF eventy
Které fungují tak, že při každém na kliku this.dataGrid zkoumají, jestli prokliknutý element je <a> s class="tableOrdering" uvnitř <tr> s class="headings" uvnitř <thead> uvnitř <table> s class="adminlisttable", nebo jestli je prokliknutý element <a> s class="filterByItem" uvnitř <tbody> s class="dataTable", nebo jestli je prokliknutý element <a> s name="unsetfilter", nebo jestli je prokliknutý element <a> s name="setfilter". Docela složitá akce, ne? Proč nepřiřazuješ události jednorázově konkrétním elementům?

jQuery UIčko
To bude hlavní brzda. Už tu na něj naříkalo více lidí.
Chceš-li obecnou radu: méně lepit, více přemýšlet.

Výrazně zpomalovat běh stránky umí též procedurální grafika. Jestli máš v CSS nějaké gradienty, stíny nebo kulaté rohy, zkus je vyházet, nebo nahradit za bitmapy.
Kajman
Profil
aDAm:
Jinak ve chrome i firefoxu (s rozšířením firebug) jde javascript profilovat - měřit, kolikrát se která funkce volá a kolik to zabralo času. Třeba Vám to pomůže rychleji najít největší brzdy.
aDAm
Profil
Chamurappi:
no jednorázově přiřazené byly původně, ale od okamžiku kdy se celý obsah načítá podle požadavku to pak byl problém a musely se vždy ty akce na ty elementy znova pověsit což byl problém v té aplikaci realizovat.

ok jQuery UI zkusím nějak vyhodit a realizivat jinak, z počátku to byla dobrá volba kvůli snadnosti implementace kdy se využívaly taby, dialogy atd.

A ano procedurální grafika tam je a je jí poměrně dost, zkusím tedy vyházet jak se to projeví.
Joker
Profil
Kajman:
Jinak ve chrome i firefoxu (s rozšířením firebug) jde javascript profilovat
Nebo Internet Explorer (8) má vestavěný profiler (a vůbec dobré nástroje pro vývojáře).
Případně i Opera má takový obecný profiler, ale na měření rychlosti JS funkcí se moc nehodí (sice tam je vidět, kolik času kdy zpracování JS zabralo, ale není tam bližší rozpad toho JS)
Chamurappi
Profil
Reaguji na aDAma:
musely se vždy ty akce na ty elementy znova pověsit což byl problém v té aplikaci realizovat
Pochybuji, že to opravdu byl problém. Akorát jsi nad tím kvůli .live nemusel přemýšlet, když jsi měl při ruce snadné špatné řešení.
Opakované jednorázové pověšení akcí na to, co se změnilo, nemusí být vždy efektivnější než využití probublávání události, ale v tomto případě nejspíš bude.

kvůli snadnosti implementace kdy se využívaly taby, dialogy atd.
Taby jdou udělat jednou změnou className a špetkou CSS. Dialogy také nejsou žádná velká věda, pokud obětuješ širokou konfigurovatelnost a nastyluješ si elementy přímo podle své potřeby.
aDAm
Profil
Chamurappi:
ano .live byla tenkrát snadná volba jak problém vyřešit, dokud se to používalo na normálním pc nebyl problém. Co takhle všechny ty .on v uvedeném příkladě spojit do jednoho a akci doplnit o logiku která ověří co bylo zmáčknuté? a podle toho provede jednu z akcí co byla rozhozena do několika .on událostí?

Ano vím že je snadné udělat taby, v částech kde se dalo spokojit s "triviálním" způsobem je již používám. Zkusím se tedy co se týká UI poohlédnout po méně "náročné" verzi.
peta
Profil
aDAm:
To je zhruba sestava meho osobniho notebooku. Kdybys dal link na demo stranku, mohl bych to otestovat. Obvykle tam ale nemam s jquery zadny problem. Takze problem bude nekde ve tvem kodu, ze neco moc opakovane volas, pouzivas.

* css - js filtry (gradient a jine efekty) - vygenerovat staticke obrazky

* js casove udalosti - setInterval, onclick, onmouseover - omezit pocet pouziti, protahnout interval
zkus mrknout, jak rychle ti jdou tyhle scripty, kdyz prejedes pres vic menu naraz:
http://peter-mlich.wz.cz/web/js/prx/efekty/mizeni/menustar.htm (interval 100ms)
http://peter-mlich.wz.cz/web/js/prx/efekty/mizeni/menustar.htm (interval 30ms)
http://peter-mlich.wz.cz/web/js/prx/efekty/vlocky/vlocky3.htm (interval 100ms 600 divu)

* co na tom pc jeste bezi? Skype? Viry? Co ukazuje ctrl+shift+esc, spravce uloh, ze v dane chvili nejvic zatezuje procesor (zalozka procesy, sloupec CPU)? Pokud nemas nic pustene, pak by stav cpu mel byt vsude nula a semtam skocit u task-manager, task-mgr na 5%. Kdyz pak pustis tu stranku, tak by to mohlo vyletet na 99% u firefoxu.

* delas tam nejake aktivni veci s grafikou? pPesun velke plochy obrazku javascriptem nebo animace? Flash animace + jquery jsou zabijak. Ono, jquery je narocne, ale zalezi na jeho pouziti.
aDAm
Profil
peta:
jo to si uvědomuju že problém bude někde v mnou dodělaných pluginech atd.

zkusil jsem odstranit veškeré animace co jsou pomocí CSS a rychlost se pohla nahoru, sice nic extra, stále bylo drobné zpoždění ale bylo to lepší.

js setinterval mám tak dvakrát, ale v jednom případě je s intervalem 5ti sec kdy dělá check na server pro stavy atd. onlick událostí je poměrně hodně, resp jsou pověšeny na hlavičky tabulek kde to řeší řazení, filtrování, stránkování atd.
K těm uvedeným skriptům, první dva jsou ok, bez zjevného problému, u toho třetího je to spomalený film ;)

co mi na pc běží? krom prohlížeče, outlooku, zend studia a wampu ještě teda skype a trillian (možná nějaký červ se najde, sice projeto x antiviry atd. ale nic nenalezeno) V task manageru je v klidu vše na nule popřípadě 1%, zbytek jsou nečinné procesy. Při zapnutí aplikace se to u FF vyšoune na nějakých cca 25%

aktivní věci s grafikou jsou, nejedná se o flash ale s pomocí jQuery se animuje nabídka, její rozbalování jinak snad nic, na několika podstránkách je ještě animované vložení nového elementu ale při testech tuhle stánku nepoužívám.


Zkusím tedy ještě nějak vymyslet demo přístupné zvenku. Předpokládám že by bylo vhodné na tom demu vypnout minifikaci co? Ať je ten js čitelný.
panther
Profil
aDAm:
Předpokládám že by bylo vhodné na tom demu vypnout minifikaci co?
ano, to by bylo vhodne :)

V task manageru je v klidu vše na nule popřípadě 1%, zbytek jsou nečinné procesy.
bavime se stale o tom EEE, kde je to pomale? Nebavime, tam by totiz Outlook, Zend Studio atp. zralo vice nez 1% (protoze s konfiguraci EEE by 1% znamenalo, ze nezere nic. Doslova.). Na tomto pocitaci, pokud jsem dobre pochopil diskusi vyse, problem s rychlosti neni, nebo se pletu?
aDAm
Profil
panther:
ano momentálně ten EEE využívám a konkrétně outlook je fakt na 0%, ZDE je taky na 0% ale bavíme se o stavu kdy tyhle appky jsou jen puštěné.
Chamurappi
Profil
Reaguji na aDAma:
Co takhle všechny ty .on v uvedeném příkladě spojit do jednoho a akci doplnit o logiku která ověří co bylo zmáčknuté?
To dělá samo jQuery, jak už jsem psal výše – takhle funguje .on. Pokud je malá pravděpodobnost, že klik v prostoru obalu je klikem do elementu páchajícího určitou činnost, neměl by být odchytáván na obalu.

Při zapnutí aplikace se to u FF vyšoune na nějakých cca 25%
Pokud je to čtyřjádro (a ne EEE, o němž měla být řeč), tak to znamená stoprocentní zatížení celého jednoho procesoru.
Aha, tak ty píšeš o EEE.
aDAm
Profil
Chamurappi:
Takže je vhodnější to místo .on pověsit přes .click a při změně obshu to vždy na nové elementy znova pověsit?

Konkrétně se jedná o EEE PC 1201N Seashell
pcmanik
Profil
aDAm:
Zamysli sa, ak budeš neustále na nový obsah pridávať udalosti ich počet bude stále narastať. Za to keď na rodiča priradíš jednu udalosť nehladiac na počet jeho potomkov a aj tých neskôr pridaných budeš mať stále len jednu udalosť, pričom potomky budú prebublávať a na rodičovi ich odchytíš.
aDAm
Profil
pcmanik:
no to je právě důvod proč jsem šel do .on když jsem procházel nějaké tipi na optimalizaci tak byl uveden příklad kde je tabulka 100x100 buňek a na každou buňku je pověšena událost onclick a že když se to rozhodi na každé TDčko tak jich bude zaregistrovaných 10000, ale když se to hodin na tabulku $('tbody').on('click', 'td', function(){}); tak se to pověsí jen jednou jen na tabulku.

ještě edit:
Ta zkrácena ukázka co je nahoře tak v plném rozsahu když se nasadí na datovou tabulku tak se registruji události:
click: změna řazení záznamů, stránkovadlo vpřed/vzad, některé sloupce obsahují odkaz po jehož kliku se provede selekce filtru v záhlaví, pak nad téměř každou buňkou je klik na vybrání řádků
enter/leave: ty jsou nad řádkem, když se přejede řádek tak se zobrazí ovládací tlačidla (editace, mazani, aktivace atd.)
change: na záhlaví tabulky, když se změní select pro filtr tak se data odfiltrují a taky stránkovadlo, resp údaj kolik záznamů na stránku.

mezitím jsou tam click události na modální okna, či akční tlačítka
peta
Profil
Ukazka - ve www prohlizecich se to dela obvykle jako Soubor - ulozit jako - uplna html - ok. :)
Pokud sis zkousel proklikat ty me priklady, tak bys zjistil, ze nevhodne udelana animace menu muze pomerne slusne zatezovat. Tam je cas pro animovani nastaveny u mne na 100ms. U tebe mozna min. 100ms = 10 kroku (vypoctu) za sekundu. Pak mam treba animaci, ktera by to mohla stihat.
http://peter-mlich.wz.cz/web/js-eff/photo/slide-pp.htm
Suta
Profil
aDAm:
Také již přes dva roky vyvíjím složitější aplikaci, v polovině vývoje jsem řešil stejný problém. Celou věc jsem vyřešil aplikováním událostí pouze nad objektem document a od té doby jsem na problémy s rychlostí nenarazil.

Zcela jistě budu za níže uvedený postup pranýřován, že je zbytečný a těžkopádný, mě však vedle odstranění problému s množstvím aplikovaných událostí nad jednotlivými elementy přinesl i přehlednější správu, jelikož veškeré události dokážu zpracovat v jediné metodě a zároveň je hned ze zdrojového kódu patrné, které události jsou s elementy svázány.

Základní kostra, která má spoustu nedostatků a v žádném případě nemůže vyhovovat v uvedené podobě. Jde však pouze o koncept:

<script type="text/javascript">
$(document)
    .on("click.document-click",function(e){
        Project.Process.click(e);
    });

Project = {};
Project.Process = {
    click: function( e ) {
        var defaultTarget = e.target,
            target = $(e.target),
            _id = target.attr("_id");

        if(!_id || _id.indexOf("c-") == -1) return;

        if(_id == "c-system-screen") {
            Project.Console.log("c-system-screen","Kliknutí levým tlačítkem na plochu");
        }
        else if(_id == "c-systemPanel-elements-main") {
            Project.Console.log("c-systemPanel-elements-main","Kliknutí levým tlačítkem na hlavní panel systému");
        }
    }
}
</script>

<a _id="c-system-screen">Hlavní plocha systému</a>
<a _id="c-systemPanel-elements-main">Hlavní panel systému</a>

Podobně jako prefix "c-" pro "click" samozřejmě používám prefixy a metody zpracování pro většinu hlavních události týkajících se myši (md- atd.).
Kcko
Profil
Suta:
$(document) .on("click.document-click",function(e){ Project.Process.click(e); });

Můžu vedět v tomto konkrétním případě na co klikáte? Kdyby to bylo pouze .document-click tak je mi to jasné. Díky
Suta
Profil
Kcko:
".document-click" je pouze rozšíření, tzn. využití jmenného prostoru pro rozlišení v případě, že by bylo potřeba aplikovat na objekt document další událost click, která by měla volat jinou obsluhu události. To však zřejmě víte, je pravda, že ve výše uvedeném případě je rozlišení zbytečné. Následující zápis tedy plní téměř stejnou úlohu.

$(document).on("click",function(e){});
« 1 2 »

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: