Autor | Zpráva | ||
---|---|---|---|
1Pupik1989 Profil |
Zdravím. Dneska nebudu tahat nic ošemetného.
Dlouhou dobu jsem brouzdal na jsperf a porovnával různé přístupy k proměnným polí a objektů. Bohužel nenašel jsem východisko jak udělat univerzální rychlé řešení pro všechny prohlížeče. Testuji inverzní funkci pro matice zde. O matice vůbec nejde, jde o ukládání proměnných do pole "m" objektu. Jak můžete vidět, tak Firefox tam kulhá. Three.js to ukládá přímo jako proměnné svého objektu. set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { this.n11 = n11; this.n12 = n12; this.n13 = n13; this.n14 = n14; this.n21 = n21; this.n22 = n22; this.n23 = n23; this.n24 = n24; this.n31 = n31; this.n32 = n32; this.n33 = n33; this.n34 = n34; this.n41 = n41; this.n42 = n42; this.n43 = n43; this.n44 = n44; return this; } Kdežto já jako pole. this.m = [ n0*det, -(m1*(m10*m15-m11*m14) - m2*(m9*m15-m11*m13) + m3*(m9*m14-m10*m13))*det, (m1*(m6*m15-m7*m14) - m2*(m5*m15-m7*m13) + m3*(m5*m14-m6*m13))*det, -(m1*(m6*m11-m7*m10) - m2*(m5*m11-m7*m9) + m3*(m5*m10-m6*m9))*det, -n4*det, (m0*(m10*m15-m11*m14) - m2*(m8*m15-m11*m12) + m3*(m8*m14-m10*m12))*det, -(m0*(m6*m15-m7*m14) - m2*(m4*m15-m7*m12) + m3*(m4*m14-m6*m12))*det, (m0*(m6*m11-m7*m10) - m2*(m4*m11-m7*m8) + m3*(m4*m10-m6*m8))*det, n8*det, -(m0*(m9*m15-m11*m13) - m1*(m8*m15-m11*m12) + m3*(m8*m13-m9*m12))*det, (m0*(m5*m15-m7*m13) - m1*(m4*m15-m7*m12) + m3*(m4*m13-m5*m12))*det, -(m0*(m5*m11-m7*m9) - m1*(m4*m11-m7*m8) + m3*(m4*m9-m5*m8))*det, -n12*det, (m0*(m9*m14-m10*m13) - m1*(m8*m14-m10*m12) + m2*(m8*m13-m9*m12))*det, -(m0*(m5*m14-m6*m13) - m1*(m4*m14-m6*m12) + m2*(m4*m13-m5*m12))*det, (m0*(m5*m10-m6*m9) - m1*(m4*m10-m6*m8) + m2*(m4*m9-m5*m8))*det ]; Další zvláštnost co nechápu, je fakt, že když použiji svoji funkci this.set(); , tak se počet operací sníží na čtvrtinu.
Viz.: set:function(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15){ this.m = [n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15]; } Napadá mě jediná možnost a to zjistit rychlost při načtení souboru. Nebo druhá varianta podle prohlížeče nastavit, jestli bude proměnná pole nebo objekt. Nicméně fajn by bylo, kdyby se našlo jednodušší a efektivnější řešení. Za každou radu děkuji. |
||
_es Profil |
#2 · Zasláno: 15. 2. 2013, 10:34:07
1Pupik1989:
A problém je v čom? V tom, že ťa prekvapuje, že nejaký skript dokáže v nejakom prehliadači pracovať efektívnejšie než iný skript? |
||
1Pupik1989 Profil |
Nejde o to, že jeden skript je rychlejší než druhý. Jde o to, že do proměnné objektu (three.js) to zapíše rychleji než do pole. Přitom dám další test pro porovnání čtení/zápis pole/objekt a pro operu vyjde pole. Takže hledám chybu, proč je ten můj skript pomalejší než by měl.
//edit: Omyl, není to v Opeře, ale ve Firefoxu. |
||
1Pupik1989 Profil |
Nezná někdo nějaké jiné fórum o webdesignu či lépe o javascriptu? Tentokrát už si asi neporadím sám.
Slibuji, že už jsem nenapíšu. |
||
Časová prodleva: 3 dny
|
|||
1Pupik1989 Profil |
#5 · Zasláno: 19. 2. 2013, 09:42:51
Nakonec vyřešeno dvěma objekty.
|
||
_es Profil |
#6 · Zasláno: 19. 2. 2013, 09:58:52
1Pupik1989:
„Slibuji, že už jsem nenapíšu.“ Problém bol v tom, že akosi nebolo jasné, akú konkrétnu radu chceš. To si čakal, že bude niekto analyzovať tvoje skripty, rôzne ich prerábať a modifikovať a vykonávať na rôznych prehliadačoch s nimi výkonové testy? |
||
1Pupik1989 Profil |
Aha, zkusím to nějak rozepsat.
Mám konstruktor třeba "Matrix". function Matrix(){}; Teď v něm potřebuji uložit 16 hodnot. No a tady začíná ten problém. Pokud v konstruktoru vytvořím pole "m", pak přístupová rychlost v Chrome je super, jenže ostatním prohlížečům se to moc nelíbí. function Matrix(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15){ this.m = ([n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15]); return this; }; Tak jsem zkusil tedy druhou nejrychlejší možnost. Uložit prostě proměnné přímo v konstruktoru. function Matrix(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15){ this.m0 = n0; this.m1 = n1; this.m2 = n2; this.m3 = n3; this.m4 = n4; this.m5 = n5; this.m6 = n6; this.m7 = n7; this.m8 = n8; this.m9 = n9; this.m10 = n10; this.m11 = n11; this.m12 = n12; this.m13 = n13; this.m14 = n14; this.m15 = n15; return this; }; To se líbí všem, ovšem zase chrome tam je jako zaseknutý. Pokud do konstruktoru přidám podmínku. function Matrix(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15){ if(chrome){ this.m = ([n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15]); }else{ this.m0 = n0; this.m1 = n1; this.m2 = n2; this.m3 = n3; this.m4 = n4; this.m5 = n5; this.m6 = n6; this.m7 = n7; this.m8 = n8; this.m9 = n9; this.m10 = n10; this.m11 = n11; this.m12 = n12; this.m13 = n13; this.m14 = n14; this.m15 = n15; } return this; }; Tak jediné co tím vyřeším, je propad rychlosti asi tak 10x. No a moje otázka zní: "Jak by mohlo nebo jaké by bylo univerzální řešení pro všechny prohlížeče?" Nenapadlo mě nic jiného, než vytvořit dva objekty a nastavit přímo ten konkrétní pro prohlížeč. Jenže to je zase spoustu zbytečného kódu navíc. |
||
_es Profil |
1Pupik1989:
Pri nejakom zložitom výpočte v JS a prístupu k veľa rôznym hodnotám by z hľadiska len efektivity rýchleho prístupu k tým hodnotám malo pomôcť všetky tie hodnoty uložiť do lokálnych premenných funkcie. Asi by bolo dobré aj trochu osvetliť, čo vlastne ten test vo výsledku testuje. |
||
1Pupik1989 Profil |
Ten test ve výsledku vlastně testuje pouze rychlost přístupu k těm proměnným. Nejlépe jak otestovat tu rychlost, mě právě napadlo vypočítat inverzní matici 4x4. Opět jsem jí předělal, teď funguje Revize 7..
To s těmi lokálními je dobrý nápad. Vůbec mě to nenapadlo. function Matrix(m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,m13,m14,m15){ return { inverse:function(){ var n0 = m5*(m10*m15-m11*m14 - m6*(m9*m15-m11*m13) + m7*(m9*m14-m10*m13)), n4 = m4*(m10*m15-m11*m14) - m6*(m8*m15-m11*m12) + m7*(m8*m14-m10*m12), n8 = m4*(m9*m15-m11*m13) - m5*(m8*m15-m11*m12) + m7*(m8*m13-m9*m12), n12 = m4*(m9*m14-m10*m13) - m5*(m8*m14-m10*m12) + m6*(m8*m13-m9*m12), det = 1/(m0*n0 + m1*n4 - m2*n8 + m3*n12); m0 = n0*det; m1 = -(m1*(m10*m15-m11*m14) - m2*(m9*m15-m11*m13) + m3*(m9*m14-m10*m13))*det; m2 = (m1*(m6*m15-m7*m14) - m2*(m5*m15-m7*m13) + m3*(m5*m14-m6*m13))*det; m3 = -(m1*(m6*m11-m7*m10) - m2*(m5*m11-m7*m9) + m3*(m5*m10-m6*m9))*det; m4 = -n4*det; m5 = (m0*(m10*m15-m11*m14) - m2*(m8*m15-m11*m12) + m3*(m8*m14-m10*m12))*det; m6 = -(m0*(m6*m15-m7*m14) - m2*(m4*m15-m7*m12) + m3*(m4*m14-m6*m12))*det; m7 = (m0*(m6*m11-m7*m10) - m2*(m4*m11-m7*m8) + m3*(m4*m10-m6*m8))*det; m8 = n8*det; m9 = -(m0*(m9*m15-m11*m13) - m1*(m8*m15-m11*m12) + m3*(m8*m13-m9*m12))*det; m10 = (m0*(m5*m15-m7*m13) - m1*(m4*m15-m7*m12) + m3*(m4*m13-m5*m12))*det; m11 = -(m0*(m5*m11-m7*m9) - m1*(m4*m11-m7*m8) + m3*(m4*m9-m5*m8))*det; m12 = -n12*det; m13 = (m0*(m9*m14-m10*m13) - m1*(m8*m14-m10*m12) + m2*(m8*m13-m9*m12))*det; m14 = -(m0*(m5*m14-m6*m13) - m1*(m4*m14-m6*m12) + m2*(m4*m13-m5*m12))*det; m15 = (m0*(m5*m10-m6*m9) - m1*(m4*m10-m6*m8) + m2*(m4*m9-m5*m8))*det; return this; } }; }; Takže zhruba takto by to mohlo vypadat? Navíc nebudu muset používat operátor new. //edit: Tak odvolávám, ten kód je blbost. |
||
_es Profil |
#10 · Zasláno: 19. 2. 2013, 12:51:14
1Pupik1989:
„Ten test ve výsledku vlastně testuje pouze rychlost přístupu k těm proměnným.“ Netestuje rýchlosť výpočtu inverznej matice? (Tip podľa názvu metód) |
||
1Pupik1989 Profil |
#11 · Zasláno: 19. 2. 2013, 13:17:58
To jo, je to výpočet na inverzní matici. Stejně tak to ale může násobení, sčítání, odčítání, dělení atd.
Mě jde hlavně o část: var m0 = this.m[0], m1 = this.m[1], m2 = this.m[2], m3 = this.m[3], m4 = this.m[4], m5 = this.m[5], m6 = this.m[6], m7 = this.m[7], m8 = this.m[8], m9 = this.m[9], m10 = this.m[10], m11 = this.m[11], m12 = this.m[12], m13 = this.m[13], m14 = this.m[14], m15 = this.m[15], a o: this.m = ([ n0*det, -(m1*(m10*m15-m11*m14) - m2*(m9*m15-m11*m13) + m3*(m9*m14-m10*m13))*det, (m1*(m6*m15-m7*m14) - m2*(m5*m15-m7*m13) + m3*(m5*m14-m6*m13))*det, -(m1*(m6*m11-m7*m10) - m2*(m5*m11-m7*m9) + m3*(m5*m10-m6*m9))*det, -n4*det, (m0*(m10*m15-m11*m14) - m2*(m8*m15-m11*m12) + m3*(m8*m14-m10*m12))*det, -(m0*(m6*m15-m7*m14) - m2*(m4*m15-m7*m12) + m3*(m4*m14-m6*m12))*det, (m0*(m6*m11-m7*m10) - m2*(m4*m11-m7*m8) + m3*(m4*m10-m6*m8))*det, n8*det, -(m0*(m9*m15-m11*m13) - m1*(m8*m15-m11*m12) + m3*(m8*m13-m9*m12))*det, (m0*(m5*m15-m7*m13) - m1*(m4*m15-m7*m12) + m3*(m4*m13-m5*m12))*det, -(m0*(m5*m11-m7*m9) - m1*(m4*m11-m7*m8) + m3*(m4*m9-m5*m8))*det, -n12*det, (m0*(m9*m14-m10*m13) - m1*(m8*m14-m10*m12) + m2*(m8*m13-m9*m12))*det, -(m0*(m5*m14-m6*m13) - m1*(m4*m14-m6*m12) + m2*(m4*m13-m5*m12))*det, (m0*(m5*m10-m6*m9) - m1*(m4*m10-m6*m8) + m2*(m4*m9-m5*m8))*det ]); Abych tu rychlost přístupu k oné proměnné var m0 = this.m[0]; nebo var m0 = this.m0; sjednotil a běželo to ve všech prohlížečích co nejrychleji. Nejde o to, že někoho mám nutnost porazit. Dělám to pro svojí online hru, kterou jsem se rozhodl udělat komplet od začátku, čili bez použití nějaké knihovny typu three.js, gl, closure atd.
|
||
_es Profil |
#12 · Zasláno: 19. 2. 2013, 13:41:55
1Pupik1989:
„To jo, je to výpočet na inverzní matici.“ To ale potom si musíš zanalyzovať, koľko je na ten výpočet potrebných operácií a s akou náročnosťou. Násobenie je náročnejšie ako súčet a pod. Spôsob uloženia medzivýsledkov môže byť zanedbateľný a môže len nepriamo ovplyvňovať náročnosť výpočtu. „rychlost přístupu k oné proměnné var m0 = this.m[0]; nebo var m0 = this.m0; “
Druhý prístup mal byť rýchlejší. Je v ňom o jeden prístup k vlastnosti objektu menej. Ak vo výsledku nie je, tak je problém asi inde. Pri nejakej optimalizácii na prístup k uloženým hodnotám, ak je x lokálna premenná, by mal byť prístup k x rýchlejší ako k objekt.vlastnosť . No rôzne prehliadače používajú rôzne vnútorné optimalizácie.
|
||
1Pupik1989 Profil |
Ano, přístup
var m0 = this.m0; by měl být rychlejší, nicméně přístup k proměnné a potom k poli var m0 = this.m[0]; to v chrome předčí.
Dá se to krásně demonstrovat na příkladu. |
||
_es Profil |
#14 · Zasláno: 19. 2. 2013, 14:48:57
1Pupik1989:
Lenže ty testuješ časť tej JS knižnice a nemôžeš vedieť, aké vedľajšie efekty tým nastanú. Ak chceš testovať prístup k premennej a prístup k poľu, musí spraviť testy, kde sa bude testovať len prístup k premennej a len prístup k poľu, nie nejaké zložité funkcie, u ktorých nie je zrejmé, ako sa s nimi prehliadač vysporiada. |
||
1Pupik1989 Profil |
Dobrá tedy. Čistě jen test Čtení/Zápis Objeckt/Pole . Výsledek je ale stejný.
Napadlo mě pole deklarovat ještě předtím, než ho pošlu do funkce. Tudíž bych nemusel používat žádný konstruktor. |
||
_es Profil |
1Pupik1989:
Nemôžeš vedieť, aké rôzne optimalizácie rôzne prehliadače robia - musíš to testovať v nejakých reálnejších situáciách. Výpočet, ktorý je „zahodený“, a je len výpočtom, môže byť napríklad ignorovaný a pod. Či nie je problém skôr s uvoľňovaním použitej pamäti, testovať by sa malo na náhodné vstupné hodnoty a pod. Môžeš ešte vyskúšať objekt vytvárať cez literálový výraz: objekt={vlastnosť1:výraz1, vlastnosť2:výraz2,...}; objekt.vlastnosť1=výraz;objekt.vlastnosť2=výraz2;...
či vytvárania poľa. |
||
1Pupik1989 Profil |
Literální zápisy jsou poslední dvě položky v testu. Na náhodné hodnoty to je opět stejné, vždycky to je stejné. Tohle je vlastně všechno taková omáčka, Já potřebuji jen vymyslet takový konstruktor objektu, který v chrome vytvoří pole a v ostatních to zapíše přímo do objektu. Minimálně 20 stylů zápisů jsem otestoval a vím, že ty dva co tu omílám jsou nejrychlejší. Pokud do konstruktoru přidám podmínku, tak si můžu jít rovnou hodit mašli, protože rychlost ve všech prohlížečích klesne tak na úroveň IE.
|
||
_es Profil |
1Pupik1989:
„Pokud do konstruktoru přidám podmínku.“ Môžeš podľa tej podmienky vytvárať odlišný konštruktor či odlišné metódy - ešte pred použitím tvojej JS knižnice. Pokiaľ ti ide o nejakú extrémnu optimalizáciu na rýchlosť, tak spomaľovať môžu aj všelijaké, nie nutné, „objektové obaly“, trebárs prechádzanie k prototypu objektu, nejaká „dedičnosť“ a pod. Alebo, prečo nepracuješ s tou maticou rovno ako s poľom, ale robíš okolo toho poľa nejaký objektový obal a pristupuješ k nemu ako k vlastnosti objektu? |
||
1Pupik1989 Profil |
_es:
„robíš okolo toho poľa nejaký objektový obal a pristupuješ k nemu ako k vlastnosti objektu“ Chtěl jsem rozlišit hlavně funkce, které vytvoří novou matici a funkce, které pracují s tou onou, kterou potřebuji. Asi to ale dopadne jak píšeš. Prostě udělám funkci Matrix.Inverse , kde první vstupní parametr bude pole.
Třeba: matice.inverse(); Měla změnit přímo pole té matice a Matrix.Inverse(matice) měla v z objektu matice vypočítat inverzi a vytvořit novou matici.
Když jako parameter budu ale posílat literální pole, tak to opět klesne u ostatních prohlížečů. Teď jsem to zatím udělal podmínkou. var Matrix4 = (window.chrome) ? Matrix4a : Matrix4o; Matrix4.CreateRotationX už jsou sdílené a pro obojí stejné. viz níže:
Matrix4.CreateRotationX = function(angle){ var c = Math.cos(angle); var s = Math.sin(angle); return new this( 1,0,0,0, 0,c,-s,0, 0,s,c,0, 0,0,0,1 ); }; Ta už vytvoří objekt podle nastaveného konstruktoru. |
||
Časová prodleva: 11 let
|
0